[YANGTOOLS-177] Optimize generated range checks Created: 30/May/14 Updated: 10/Apr/22 Due: 31/Jul/14 Resolved: 01/Aug/14 |
|
| Status: | Resolved |
| Project: | yangtools |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | ||
| Reporter: | Robert Varga | Assignee: | Ladislav Borak |
| Resolution: | Done | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
Operating System: All |
||
| Issue Links: |
|
||||||||
| Description |
|
Profiling cbench I have encountered performance overhead when constructing FlowCookie class – 20528ms for 105187 invocations. Of that, 15894ms was spent in Range.closed() invocations. Looking at the generated code: public FlowCookie(BigInteger _value) { } } It is rather obvious we can do better: 1) those range constraints should be lazily generated, but retained as static fields (double-checked loading) 2) BigInteger("0") should be replaced with BigInteger.ZERO (also ONE and TEN) 3) For values less that Long.MAX_VALUE, we should use BigInteger.valueOf(long) 4) rangeConstraints should end up being an ImmutableList |
| Comments |
| Comment by Martin Vitez [ 11/Jun/14 ] |
|
Proposed patch: |
| Comment by Rob Adams [ 08/Jul/14 ] |
|
It looks like the result of the code here is still incorrect. This is attempting to do a double-checked lock pattern in an incorrect way with the Java memory model. See http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html public static List<Range<BigInteger>> length() { } In this case the (easy) correct fix is to use the static singleton pattern by declaring the _length field as a static variable in a subclass with a static initializer. It will be automatically initialized on the first access just as the code here is attempting to do. |
| Comment by Robert Varga [ 08/Jul/14 ] |
|
Agreed, that double-checked locking is my mistake (and now I have to hunt for all the paces I proliferated it). Not sure what an inner class will cost us in terms of memory overhead. We may need to do some profiling and tradeoff juggling. |
| Comment by Rob Adams [ 08/Jul/14 ] |
|
Given that this is a static variable the additional memory overhead is irrelevant. If you're doing this on an instance variable just setting it as volatile should fix your code. |
| Comment by Robert Varga [ 08/Jul/14 ] |
|
So we have the following options: 1) do proper locking by protecting the entire check in a synchronized block I would opt for 3), except it may enlarge our PermGen footprint. I suspect we are usually very close to allocating an object when we touch the class, so 4) may actually make sense, too. Opinions? |
| Comment by Robert Varga [ 08/Jul/14 ] |
|
Well, the holder is a class, which needs to be loaded into pergen and be left there. While it is insignificant overhead compared to objects, given that we have thousands of classes, that overhead may pile up. |
| Comment by Rob Adams [ 08/Jul/14 ] |
|
Oh I thought you'd done the lazy initialization because you were benchmarking this. If not, I'd say just move the initialization to a static block pending some evidence that lazy loading is useful. |
| Comment by Robert Varga [ 09/Jul/14 ] |
|
Thinking about this a bit more, we do not need any locking at all. The reasoning is the following:
There are no ill side-effects from threads seeing different instances of the state – since it is immutable, it is bound to behave the same. Since they are not referenced by instances, we are not running the risk of leaking multiple instances to the heap in general. Resolution of which instance will actually survive is amortized. Does this sounds correct, or am I missing something? |
| Comment by Dana Kutenicsova [ 25/Jul/14 ] |
|
+1 on removing double-check for null (it creates Findbug issue). |
| Comment by Robert Varga [ 26/Jul/14 ] |
|
So let's lose the lazy initialization and perform it on class load, using normal constant field. That should cut the complexity. |
| Comment by Ladislav Borak [ 30/Jul/14 ] |
|
proposed patch: https://git.opendaylight.org/gerrit/#/c/9483/ |