Sherman,

I like your suggestions and will open an issue to work on the performance after 
integration.  I’ll fix the minor “bug” you pointed out at the same time.  

Steve

> On Feb 12, 2016, at 5:19 PM, Xueming Shen <xueming.s...@oracle.com> wrote:
> 
> 
> Steve,
> 
> I would assume the difference of the webrev.04 "old" iterator and the 
> webrev.06 "new" iterator
> that might trigger a performance is how you create the JarFileEntry. The one 
> parameter constructor
> invokes isMultiRelease(), which might be relatively expensive, when the "mr" 
> is enabled. There
> are couple "if" checks involved. 
> 
> For the "new" iterator is slower than the current jdk9 one. It might be 
> desired to have two JarEntryIterator
> classes defined, one for "notVersioned", one for the "versioned". Of course 
> keep the two parameter
> constructor for the "notVersioned". This might bring performance back for the 
> normal "notVersioned"
> usage, which I would assume is the majority.
> 
> There is also a "bug" in the new iterator. The iterator/Enumeration returned 
> from ZipFile.entries()
> checks "ensureOpen() in both hasNext() and next(). So close() the ZipFile 
> after itr.hasNext() will
> fails the next next() invocation in the old implementation. The latest itr 
> will returns the cached 
> "ze". Not a big issue for sure, but a kind of "regression". Defining two 
> iterator classes as suggested
> above will also workaround this issue, as the "notVersioned" one will work 
> just as expected, no
> regression.
> 
> -Sherman
> 
> On 2/9/16 5:04 PM, Steve Drach wrote:
>> Hi,
>> 
>> Yet another webrev, http://cr.openjdk.java.net/~sdrach/8132734/webrev.06/ 
>> <http://cr.openjdk.java.net/%7Esdrach/8132734/webrev.06/>, with a change to 
>> JarEntryIterator to fix a problem discovered by performance tests — calling 
>> hasNext() twice as often as needed.  I also removed the @since 9 tags from 
>> the methods entries() and stream(), and added an additional sentence to the 
>> spec for each of those methods that clarifies what a base entry is (actually 
>> is not).
>> 
>>> I think having stream and entries do this is right although I would like to 
>>> see some performance data if possible.
>> 
>> See http://cr.openjdk.java.net/~sdrach/8132734/JarFile%20Performance.pdf 
>> <http://cr.openjdk.java.net/%7Esdrach/8132734/JarFile%20Performance.pdf>
>> 
>> I used JMH to run the benchmark.  See 
>> http://cr.openjdk.java.net/~sdrach/8132734/MyBenchmark.java 
>> <http://cr.openjdk.java.net/%7Esdrach/8132734/MyBenchmark.java>.  I used two 
>> jar files, the rt.jar file from JDK 8 that has 20653 entries and the 
>> multi-release.jar found in the test directory with 14 entries.  Obviously 
>> rt.jar is not a multi-release jar file.
>> 
>> The first two tables (1 and 2) are comparable and the second two tables are 
>> somewhat comparable (3 and 4).
>> 
>> Tables 1 and 2 have 4 sections that show the results of tests on the two jar 
>> files in 4 configurations of JarFile.  The tests were done with a JarFile 
>> object constructed without the Release object argument, essentially the 
>> legacy constructor.  The section labeled "JDK 8 JarFile” was done with JDK 
>> 8u66.  The section labeled “JDK 9 JarFile” was done with the latest build of 
>> openjdk/jdk9/dev without any changes in my 8132734 changeset.  I chose this 
>> section as the reference, so the last column shows the values normalized to 
>> 1 micro/milli second per operation (rt.jar times are in milliseconds and 
>> multi-release.jar times are in microseconds).  It should be obvious that JDK 
>> 9 is much faster than JDK 8, somewhere on the order of 5-6 times faster.  I 
>> think that is because ZipFile doesn’t use JNI in JDK 9.
>> 
>> Of the two remaining sections in Tables 1 and 2, the section labeled 
>> “MultiRelease JarFile” differs from the section labeled “MultiRelease 
>> JarFile, new iterator” only in the JarEntryIterator class.  The first one 
>> uses the original iterator in JarFile.java that can be seen starting with 
>> line 551 of webrev.04 
>> <http://cr.openjdk.java.net/%7Esdrach/8132734/webrev.04/>, and the new 
>> iterator starts with line 553 of webrev.06 
>> <http://cr.openjdk.java.net/%7Esdrach/8132734/webrev.06/>.  The results are 
>> strange.  The new, more complex, iterator appears to be faster than the old, 
>> simpler, iterator.  I double, and triple, checked it, but it was always 
>> faster.  I used jitwatch to look at the hotspot logs generated during 
>> compilation and neither method was compiled.  I suppose I could dig into it 
>> further but decided not to.  Consider it good news.  The results do show 
>> that the multi-release enhancement slows JarFile entries/stream down by 
>> 2-18% depending on the size of the jar file.  But they are still much better 
>> than the JDK 8 values.
>> 
>>> Also I would expect that if a JAR file is not mult-release but the library 
>>> opens it with Release.RUNTIME to perform the same as opening the JAR file 
>>> with the Release-less constructors.
>> 
>> The results in Table 3 attempts to answer this question since rt.jar is not 
>> a multi-release jar file.  This tells me that if one opens the JarFile with 
>> Release.RUNTIME, that there is a performance penalty of 2-6% on this very 
>> large jar file.
>> 
>> Finally, the results in Table 4 tell me that processing a true multi-release 
>> jar file takes about 80% more time per entries() or stream() operation.  
>> I’ve looked at this in a profiler and there is no particular area that 
>> stands out to me, it’s just more complicated to process a multi-release jar 
>> file, as would be expected.
>> 
>>> I think the javadoc will need to also need to make it clear whether entries 
>>> with names starting with META-INF/versions/ are returned.
>> 
>> Fixed.
>> 
>>> 
>>> I see you've added @since 9 to the existing methods, I assume you didn't 
>>> mean to do this.
>> 
>> Fixed.
>> 
>>> 
>>> At some point then we need to discuss how RUNTIME_VERSION is computed. Iris 
>>> (via Mandy) has pushed jdk.Version to jdk9/dev but having it exported by 
>>> java.base conflicts with the design principles in JEP 200. Moving it to 
>>> another module means that code in java.base cannot use it and thus the JAR 
>>> file can't use it.
>> 
>> Left as is.
>> 
> 

Reply via email to