United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 7162188 Performance hits when application code calling getResourceAsStream
7162188 : Performance hits when application code calling getResourceAsStream

Details
Type:
Bug
Submit Date:
2012-04-17
Status:
Resolved
Updated Date:
2012-08-22
Project Name:
JDK
Resolved Date:
2012-05-09
Component:
deploy
OS:
generic
Sub-Component:
deployment_toolkit
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
6u31
Fixed Versions:
8

Related Reports
Backport:
Relates:
Relates:
Relates:

Sub Tasks

Description
Noticeable performance degradation b/w JRE 1.5 and JRE 1.6 for applications with large number of calls to getResourceAsStream().
The original BugDB number is https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=13059819

==================== email from ###@###.### ===================
One of our customers, Correctional Service of Canada, is trying to move
its client machines from JDK 5u18 to JDK 6uX, and they see a significant
performance regression with their application (escalated as
https://bug.oraclecorp.com/pls/bug/webbug_print.show?c_rptno=13059819).
I found out that it is related to Java Deployment Cache implementation.
Could you please suggest how we could fix it?

The regression is reproducible with all JDK 6 update releases starting with
initial JDK 6 FCS. Here are some numbers showing the regression scale:

          5.0u18   5.0u35   6        6u31     7
---------------------------------------------------
Test 1:   8 sec    7 sec   16 sec   22 sec   22 sec
Test 2:   1 sec    1 sec    3 sec    3 sec    3 sec
Test 3:   5 sec    5 sec   12 sec   14 sec   14 sec

I performed initial investigation and profiling and found out the following:
- The performance regression is caused by redesign of the Java Deployment Cache
  subsystem. Initially a huge performance regression appeared in JDK 6 b38
  with the fix for
  CR 6245224: JCK15: multiple tests hang under api/java_net, plugin , mustang
  In the later JDK 6 builds the performance significantly improved but has
  never recovered to the level of JDK 5.
- Profiling showed that the key difference is in the execution time of
  the following method:
  sun.plugin.net.protocol.jar.CachedJarURLConnection.getContent()
  For example, in Test 3 with JDK 6 b37 it uses about 0% of CPU time, but
  in the same test case with JDK 6u31 it uses 58% - this is actually very close
  to the size of the performance regression itself.

Basically, the test case loads a big number (80-120) of resource files from
a large (80 MB) JAR file. As I understand, on every load request
(java.net.URL.getContent() or java.net.URL.openStream()), the deployment code
in 6u31 ends up with reading the whole JAR file:

...
java.net.URL.getContent()
sun.plugin.net.protocol.jar.CachedJarURLConnection.getContent()
sun.plugin.net.protocol.jar.CachedJarURLConnection.connect()
sun.net.www.protocol.jar.JarURLConnection.connect()
sun.net.www.protocol.jar.JarFileFactory.get(URL, boolean)
sun.net.www.protocol.jar.URLJarFile.getJarFile(URL, URLJarFile$URLJarFileCloseController)
sun.net.www.protocol.jar.URLJarFile.retrieve(URL, URLJarFile$URLJarFileCloseController)
sun.plugin.PluginURLJarFileCallBack.retrieve(URL)
sun.plugin.PluginURLJarFileCallBack$2.run()
sun.plugin.PluginURLJarFileCallBack.access$000(PluginURLJarFileCallBack, URLConnection, String, boolean)
sun.plugin.PluginURLJarFileCallBack.downloadJAR(URLConnection, String, boolean)
java.io.FilterInputStream.read(byte[])
... 
============= end of email from ###@###.### ===================
================= email from ###@###.### ==================
Hello Nam,

Unfortunately, there is no standalone test case for this issue, but we have
access to their web application and a detailed description of actions
that are considered as "test cases" (attached).

The problem is a bit different: the jar file _is_ cached, but on-demand
access to the resources in this cached jar file is much slower in
JDK 6uX/7uX than in 5uX.

----------
1. Go to the following URL:
http://orldss-01.us.oracle.com/discoverer/app/connection?event=displayConnections&clientType=plus

2. Connect To = OracleBI Discoverer for OLAP
   Username = scott
   @ Password = tiger
   Database = dss

3. This will open the OLAP Connect screen.
   Username = scott
   @ Password = tiger
   Host = orldss-apps.us.oracle.com
   Port = 1522
   SID = dss

4. Follow Steps_to_perform_Java_test.docx (attachement)

                                    

Comments
EVALUATION

Fixed as described in webrev:
  http://sa.us.oracle.com/mail-archive/7162188-deployment
Pushed to 8 with changeset:
  http://closedjdk.us.oracle.com/jdk8/deploy/deploy/rev/162db3ffaff4

Nicholay, please help with verify the performance improvement to be on par with 1.5.
                                     
2012-05-03
EVALUATION

Calling getResourceAsStream() on deploy class loaders (Applet2ClassLoader in this case), would result in open new connection to the URL both in JRE 7 and JRE 6.  This lead to creating new CachedJarFile for each calls.

The fix is avoid doing super.getResourceAsStream() instead trying getResourceAsResource first to get the input stream for the resource entry from the existing class path jar loader jar file.
                                     
2012-04-17



Hardware and Software, Engineered to Work Together