日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

What Influences Method Call Performance in Java?--reference

發(fā)布時間:2025/4/5 java 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 What Influences Method Call Performance in Java?--reference 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

reference from:https://www.voxxed.com/blog/2015/02/too-fast-too-megamorphic-what-influences-method-call-performance-in-java/

Whats this all about then?

Let’s start with a short story. I?proposed a change?on the a Java core libs mailing list to override some methods which are currently?final. This stimulated several discussion topics – one of which was the extent to which a performance regression would be introduced by taking a method which was?final?and stopping it from being?final.

I had some ideas about whether there would be a performance regression or not, but I put these aside to try and enquire as to whether there were any sane benchmarks published on the subject. Unfortunately I couldn’t find any. That’s not to say that they don’t exist or that other people haven’t investigated the situation, but that I didn’t see any public peer-reviewed code. So – time to write some benchmarks.

Benchmarking Methodology

So I decided to use the ever-awesome?JMH?framework in order to put together these benchmarks. If you aren’t convinced that a framework will help you get accurate benchmarking results then you should look at this?talk by Aleksey Shipilev, who wrote the framework, or?Nitsan Wakart’s?really cool blog post which explains how it helps.

In my case I wanted to understand what influenced the performance of method invocation. I decided to try out different variations of methods calls and measure the cost. By having a set of benchmarks and changing only one factor at a time, we can individually rule out or understand how different factors or combinations of factors influence method invocation costs.

Inlining

Let’s squish these method callsites down.

Simultaneously the most and least obvious influencing factor is whether there is a method call at all! It’s possible for the actual cost of a method call to be optimized away entirely by the compiler. There are, broadly speaking, two ways to reduce the cost of the call. One is to directly inline the method itself, the other is to use an inline cache. Don’t worry – these are pretty simple concepts but there’s a bit of terminology involved which needs to be introduced. Let’s pretend that we have a class called?Foo, which defines a method called?bar.

1 2 3 class Foo { ??void bar() { ... } }

We can call the?bar?method by writing code that looks like this:

1 2 Foo foo = new Foo(); foo.bar();

The important thing here is the location where bar is actually invoked –?foo.bar()?– this is referred to as a?callsite. When we say a method is being “inlined” what is means is that the body of the method is taken and plopped into the callsite, in place of a method call. For programs which consist of lots of small methods (I’d argue, a properly factored program) the inlining can result in a significant speedup. This is because the program doesn’t end up spending most of its time calling methods and not actually doing work! We can control whether a method is inlined or not in JMH by using the?CompilerControl?annotations. We’ll come back to the concept of an inline cache a bit later.

Hierarchy Depth and Overriding Methods

Do parents slow their children down?

If we’re choosing to remove the?final?keyword from a method it means that we’ll be able to override it. This is another factor which we consequently need to take into account. So I took methods and called them at different levels of a class hierarchy and also had methods which were overridden at different levels of the hierarchy. This allowed me to understand or eliminate how deep class hierarchies interfere with overriding costs.

Polymorphism

Animals: how any OO concept is described.

When I mentioned the idea of a callsite earlier I sneakily avoided a fairly important issue. Since it’s possible to override a non-finalmethod in a subclass, our callsites can end up invoking different methods. So perhaps I pass in a Foo or it’s child – Baz – which also implements a bar(). How does your compiler know which method to invoke? Methods are by default virtual (overridable) in Java it has to lookup the correct method in a table, called a vtable, for every invocation. This is pretty slow, so optimizing compilers are always trying to reduce the lookup costs involved. One approach we mentioned earlier is inlining, which is great if your compiler can prove that only one method can be called at a given callsite. This is called a?monomorphic?callsite.

Unfortunately much of the time the analysis required to prove a callsite is monomorphic can end up being impractical. JIT compilers tend to take an alternative approach of profiling which types are called at a callsite and guessing that if the callsite has been monomorphic for it’s first N calls then it’s worth speculatively optimising based on the assumption that it always will be monomorphic. This speculative optimisation is frequently correct, but because it’s not always right the compiler needs to inject a guard before the method call in order to check the type of the method.

Monomorphic callsites aren’t the only case we want to optimise for though. Many callsites are what is termed?bimorphic?– there are two methods which can be invoked. You can still inline bimorphic callsites by using your guard code to check which implementation to call and then jumping to it. This is still cheaper than a full method invocation. It’s also possible to optimise this case using an inline cache. An inline cache doesn’t actually inline the method body into a callsite but it has a specialised jump table which acts like a cache on a full vtable lookup. The hotspot JIT compiler supports bimorphic inline caches and declares that any callsite with 3 or more possible implementations is?megamorphic.

This splits out 3 more invocation situations for us to benchmark and investigate: the monomorphic case, the bimorphic case and the megamorphic case.

Results

Let’s groups up results so it’s easier to see the wood from the trees, I’ve presented the raw numbers along with a bit of analysis around them. The specific numbers/costs aren’t really of that much interest. What is interesting is the ratios between different types of method call and that the associated error rates are low. There’s quite a significant difference going on – 6.26x between the fastest and slowest. In reality the difference is probably larger because of the overhead associated with measuring the time of an empty method.

The source code for these benchmarks is available on?github. The results aren’t all presented in one block to avoid confusion. The polymorphic benchmarks at the end come from running?PolymorphicBenchmark, whilst the others are from?JavaFinalBenchmark

Simple Callsites

Our first set of results compare the call costs of a virtual method, a?final?method and a method which has a deep hierarchy and gets overridden. Note that in all these cases we’ve forced the compiler to not inline the methods. As we can see the difference between the times is pretty minimal and and our mean error rates show it to be of no great importance. So we can conclude that simply adding thefinalkeyword isn’t going to drastically improve method call performance. Overriding the method also doesn’t seem to make much difference either.

Inlining Simple Callsites

Now, we’ve taken the same three cases and removed the inlining restriction. Again the?final?and virtual method calls end up being of a similar time to each other. They are about 4x faster than the non-inlineable case, which I would put down to the inlining itself. The always overridden method call here ends up being between the two. I suspect that this is because the method itself has multiple possible subclass implementations and consequently the compiler needs to insert a type guard. The mechanics of this are explained above in more detail under?Polymorphism.

Class Hierarchy Impact

Wow – that’s a big block of methods! Each of the numbered method calls (1-4) refer to how deep up a class hierarchy a method was invoked upon. So?parentMethod4?means we called a method declared on the 4th parent of the class. If you look at the numbers there is very little difference between 1 and 4. So we can conclude that hierarchy depth makes no difference. The inlineable cases all follow the same pattern: hierarchy depth makes no difference. Our inlineable method performance is comparable toinlinableAlwaysOverriddenMethod, but slower than?inlinableVirtualInvoke. I would again put this down to the type guard being used. The JIT compiler can profile the methods to figure out only one is inlined, but it can’t prove that this holds forever.

Class Hierarchy Impact on?final?methods

This follows the same pattern as above – the?final?keyword seems to make no difference. I would have thought it was possible here, theoretically, for?inlinableParentFinalMethod4?to be proved inlineable with no type guard but it doesn’t appear to be the case.

Polymorphism

Finally we come to the case of polymorphic dispatch. Monomorphoric call costs are roughly the same as our regular virtual invoke call costs above. As we need to do lookups on larger vtables, they become slower as the bimorphic and megamorphic cases show. Once we enable inlining the type profiling kicks in and our monomorphic and bimorphic callsites come down the cost of our “inlined with guard” method calls. So similar to the class hierarchy cases, just a bit slower. The megamorphic case is still very slow. Remember that we’ve not told hotspot to prevent inlining here, it just doesn’t implement polymorphic inline cache for callsites more complex than bimorphic.

What did we learn?

I think it’s worth noting that there are plenty of people who don’t have a performance mental model that accounts for different types of method calls taking different amounts of time and plenty of people who understand they take different amounts of time but don’t really have it quite right. I know I’ve been there before and made all sorts of bad assumptions. So I hope this investigation has been helpful to people. Here’s a summary of claims I’m happy to stand by.

  • There is a big difference between the fastest and slowest types of method invocation.
  • In practice the addition or removal of the?final?keyword doesn’t really impact performance, but, if you then go and refactor your hierarchy things can start to slow down.
  • Deeper class hierarchies have no real influence on call performance.
  • Monomorphic calls are faster than bimorphic calls.
  • Bimorphic calls are faster than megamorphic calls.
  • The type guard that we see in the case of profile-ably, but not provably, monomorphic callsites does slow things down quite a bit over a provably monomorphic callsite.

I would say that the cost of the type guard is my personal “big revelation”. It’s something that I rarely see talked about and often dismissed as being irrelevant.

Caveats and Further Work

Of course this isn’t a conclusive treatment of the topic area!

  • This blog has just focussed on type related factors surrounding method invoke performance. One factor I’ve not mentioned is the heuristics surrounding method inlining due to body size or call stack depth. If your method is too large it won’t get inlined at all, and you’ll still end up paying for the cost of the method call. Yet another reason to write small, easy to read, methods.
  • I’ve not looked into how invoking over an interface affects any of these situations. If you’ve found this interesting then there’s an investigation of invoke interface performance on the?Mechanical Sympathy?blog.
  • One factor that we’ve completely ignored here is the impact of method inlining on other compiler optimisations. When compilers are performing optimisations which only look at one method (intra-procedural optimisation) they really want as much information as they can get in order to optimize effectively. The limitations of inlining can significantly reduce the scope that other optimisations have to work with.
  • Tying the explanation right down to the assembly level to dive into more detail on the issue.

Perhaps these are topics for a future blog post.

Thanks to?Aleksey Shipilev?for feedback on the benchmarks and to?Martin Thompson, Aleksey,?Martijn Verburg, Sadiq Jaffer and?Chris West?for the very helpful feedback on the blog post.

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/4304652.html

總結(jié)

以上是生活随笔為你收集整理的What Influences Method Call Performance in Java?--reference的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产后入清纯学生妹 | 97超碰碰碰 | 日本美女性爱视频 | 久久久亚洲精品视频 | 成人一区二区三区仙踪林 | 日本在线高清视频 | 无码粉嫩虎白一线天在线观看 | 欧美日韩在线不卡 | 国内自拍区 | 在线视频麻豆 | 处破痛哭a√18成年片免费 | 国产精选毛片 | 极品女神无套呻吟啪啪 | 福利在线观看 | 国产.com | 一区二区三区视频 | 欧美大片一区二区三区 | 欧美久久久影院 | 精品视频在线播放 | gav久久| 毛片大全在线观看 | 97国产精品久久 | 国产精品美女久久久久久 | 日韩欧美在线观看 | 网红av在线| 男女视频在线免费观看 | 国产热视频 | 日本女人毛茸茸 | 国产 日韩 欧美 成人 | 亚洲激情一区 | 黄色1级片| 二级黄色片 | 亚洲视频一二区 | 久久久久久毛片 | 综合激情在线 | 久久久久亚洲精品系列色欲 | 久久久不卡国产精品一区二区 | 国产精品不卡一区 | 国产精品第8页 | 日韩一区久久 | 91玉足脚交嫩脚丫在线播放 | 亚洲天堂女人 | 用力插视频 | 亚洲最大视频网站 | 国产精品情侣 | 一本色道久久综合狠狠躁的推荐 | 日本精品在线观看视频 | 高清不卡毛片 | 午夜黄色在线 | 亚洲男女啪啪 | 99黄色 | 久草老司机 | 日本国产一区 | 18精品爽国产白嫩精品 | 吞精囗交69激情欧美 | 色婷婷在线视频 | 亚洲精品高清在线观看 | 国产h视频在线 | 亚洲区免费 | av加勒比| 国产精品一区网站 | 三级免费观看 | 日本免费网址 | xxxxxxxx黄色片 | 国产精品色婷婷99久久精品 | 亚洲日本香蕉 | 男人舔女人下部高潮全视频 | 欧美久久久久久久久久久 | avtt香蕉久久 | 99re伊人 | 色屁屁网站 | 极品美女啪啪 | 久久国产劲爆∧v内射 | 狂野少女电影在线观看国语版免费 | 久久国产黄色片 | 涩涩网址 | 久久乐视频 | 国产一二区在线观看 | 在线精品小视频 | 激情网色| 精品国产69| 亚洲国产精品久久人人爱 | 91日韩| 日日夜夜天天干 | 亚洲精品人妻av | 青青草免费在线观看视频 | 久久午夜精品 | 国产伦精品一区二区三区88av | 两性动态视频 | 国产精品久久久久久无人区 | 永久免费精品视频 | 国语粗话呻吟对白对白 | 国产91亚洲精品 | 中文综合网 | 久久精品观看 | 五月婷婷色丁香 | 久久久久久久久久成人 | 亚洲一级中文字幕 | 乌克兰极品av女神 |