{"action":"created","issue":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/11862","labels_url":"https://api.github.com/repos/JuliaLang/julia/issues/11862/labels{/name}","comments_url":"https://api.github.com/repos/JuliaLang/julia/issues/11862/comments","events_url":"https://api.github.com/repos/JuliaLang/julia/issues/11862/events","html_url":"https://github.com/JuliaLang/julia/pull/11862","id":91060079,"number":11862,"title":"RFC: Try implement callsite cache for runtime dynamic generic function call","user":{"login":"yuyichao","id":712232,"avatar_url":"https://avatars.githubusercontent.com/u/712232?v=3","gravatar_id":"","url":"https://api.github.com/users/yuyichao","html_url":"https://github.com/yuyichao","followers_url":"https://api.github.com/users/yuyichao/followers","following_url":"https://api.github.com/users/yuyichao/following{/other_user}","gists_url":"https://api.github.com/users/yuyichao/gists{/gist_id}","starred_url":"https://api.github.com/users/yuyichao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yuyichao/subscriptions","organizations_url":"https://api.github.com/users/yuyichao/orgs","repos_url":"https://api.github.com/users/yuyichao/repos","events_url":"https://api.github.com/users/yuyichao/events{/privacy}","received_events_url":"https://api.github.com/users/yuyichao/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/JuliaLang/julia/labels/performance","name":"performance","color":"d7e102"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-06-25T19:56:41Z","updated_at":"2015-11-08T18:34:37Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/JuliaLang/julia/pulls/11862","html_url":"https://github.com/JuliaLang/julia/pull/11862","diff_url":"https://github.com/JuliaLang/julia/pull/11862.diff","patch_url":"https://github.com/JuliaLang/julia/pull/11862.patch"},"body":"This is my attempt to implement @carnaval 's JSoC idea.\r\n\r\nIt has a few hacky point (rooting function objects, the way it gives up on types as argument).\r\n\r\nThe current implementation shows a speed up of ~20% for a no-op function call and is about 7x slower than a direct non-inlined callsite using the following [benchmark](https://github.com/yuyichao/explore/blob/master/julia/callsite_cache/bench.jl)\r\n\r\n```julia\r\n@noinline f1(a::ANY, b::ANY) = nothing\r\n@noinline f2(a::ANY, b::ANY) = a + b\r\n\r\nk1(a::ANY, b::ANY, n) = for i in 1:n\r\n    f1(a, b)\r\nend\r\n\r\nk2(a::ANY, b::ANY, n) = for i in 1:n\r\n    f2(a, b)\r\nend\r\n\r\n@noinline f3(a, b) = a + b\r\n\r\nk3(a::ANY, b::ANY, n) = for i in 1:n\r\n    f3(a, b)\r\nend\r\n\r\nk4(a, b, n) = for i in 1:n\r\n    f3(a, b)\r\nend\r\n\r\nk5(n) = for i in 1:n\r\n    f2(1, 2)\r\nend\r\n\r\nk1(1, 2, 3)\r\nk2(1, 2, 3)\r\nk3(1, 2, 3)\r\nk4(1, 2, 3)\r\nk5(3)\r\n\r\n@time k1(1, 2, 100_000_000)\r\n@time k2(1, 2, 100_000_000)\r\n@time k3(1, 2, 100_000_000)\r\n@time k4(1, 2, 100_000_000)\r\n@time k5(100_000_000)\r\n\r\n# Profile.clear()\r\n# @profile k3(1, 2, 300_000_000)\r\n# Profile.print(C=true)\r\n```\r\n\r\nNote that `k4` is a direct callsite version of `k3` for comparason.\r\n\r\nOutput on master\r\n```julia\r\n   1.502 seconds      (156 allocations: 10760 bytes)\r\n   3.172 seconds      (4 allocations: 144 bytes)\r\n   1.515 seconds      (4 allocations: 144 bytes)\r\n 175.886 milliseconds (4 allocations: 144 bytes)\r\n   2.496 seconds      (4 allocations: 144 bytes)\r\n```\r\n\r\nWith this PR\r\n```julia\r\n   1.173 seconds      (156 allocations: 10760 bytes)\r\n   2.571 seconds      (4 allocations: 144 bytes)\r\n   1.256 seconds      (4 allocations: 144 bytes)\r\n 183.999 milliseconds (4 allocations: 144 bytes)\r\n   1.709 seconds      (4 allocations: 144 bytes)\r\n```\r\n\r\nUnfortunately (for fortunately) the base is reasonably well written so the speedup in the test is not very visible (although it also doesn't show any slowdown). This is also my first time to write any code that is very cache sensitive so suggestions are definitely welcome.\r\n\r\n@JeffBezanson "},"comment":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/comments/154856051","html_url":"https://github.com/JuliaLang/julia/pull/11862#issuecomment-154856051","issue_url":"https://api.github.com/repos/JuliaLang/julia/issues/11862","id":154856051,"user":{"login":"JeffBezanson","id":744556,"avatar_url":"https://avatars.githubusercontent.com/u/744556?v=3","gravatar_id":"","url":"https://api.github.com/users/JeffBezanson","html_url":"https://github.com/JeffBezanson","followers_url":"https://api.github.com/users/JeffBezanson/followers","following_url":"https://api.github.com/users/JeffBezanson/following{/other_user}","gists_url":"https://api.github.com/users/JeffBezanson/gists{/gist_id}","starred_url":"https://api.github.com/users/JeffBezanson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JeffBezanson/subscriptions","organizations_url":"https://api.github.com/users/JeffBezanson/orgs","repos_url":"https://api.github.com/users/JeffBezanson/repos","events_url":"https://api.github.com/users/JeffBezanson/events{/privacy}","received_events_url":"https://api.github.com/users/JeffBezanson/received_events","type":"User","site_admin":false},"created_at":"2015-11-08T18:34:37Z","updated_at":"2015-11-08T18:34:37Z","body":"In #13412, so far the jlcall convention is the same. However it is only used internally for methods; the ABI for doing a normal julia function call is to just call `jl_apply_generic`. Passing types separately in jlcall seems like it will be a lot more complicated and expensive in general.\r\n\r\nI think the less-code version of this is worth pursuing. Are you sure it's that much slower?"}}