You really never know what is going to happen to code once it is passes
through the JIT compiler. The "if" statement may be converted to a
switch statement. The "if" statement may be inlined. The only way to
tell is to time the code in isolation. Can you write a test case that
tests just the parser code in isolation? If you can write a isolated
test, don't forget to run the test twice to force the JIT compiler to
kick in and then throw out the first result. One final thing, a VM
can't really accurately measure a single period shorter then 500 ms. I
normally do some work in a for loop with a few thousand or million
iterations depending on the thing being measured. I time the entire
loop, and divid by the number of iterations to get to the time for a
single loop (normally in nanoseconds).
-dain
On Dec 22, 2004, at 2:45 PM, RPost wrote:
Does anyone have any experience or knowledge about the JavaCC process
used to produce SQLParser.java?
�
There are two�functions,�jj_3R_315() and jj_3R_338(),�in
SQLParser.java that are very poorly optimized.
�
jj_3R_315 contains around 115 nested IF statements and jj_3R_338
contains over 200 nested IF statements.
�
The statement: �� PreparedStatement pstmt =
con.prepareStatement("insert into table1 values (?)");
winds up calling jj_3R_315 three times. For each call the current
token position is at the "(" and the function executes the entire
chain of 115 calls:
�
��� if (jj_scan_token(208)) {
��� jj_scanpos = xsp;
��� if (jj_scan_token(209)) {
��� jj_scanpos = xsp;
��� ... over 100 more nested if statements before finishing.
�
A stack trace shows that the actual call to�jj_3R_315 is about 15
layers deep:
�
jj_3_9
� jj_3R_51
��� jj_3R_91
����� jj_3R_167, which calls 204, 261, 289, 310, 322, 333, 337, 343,
jj_3R_315
�
Most of the calling functions do no more than call one function and
returns its boolean result.
�
I have not been able to create code that calls the jj_3R_338 function
but it is similar in structure with a depth of over 200 nested 'if'
statements. Each 'if' calls the jj_scan_token() function.
�
The sysinfo for this is:
�
D:\cloudscape_derby\test>d:\jdk1.3.1\bin\java -classpath
.;..\lib\derby.jar;..\lib\derbynet.jar;..\lib\derbytools.jar
org.apache.derby.tools.sysinfo
------------------ Java Information ------------------
Java Version:��� 1.3.1
Java Vendor:���� Sun Microsystems Inc.
Java home:������ d:\jdk1.3.1\jre
Java classpath:�
.;..\lib\derby.jar;..\lib\derbynet.jar;..\lib\derbytools.jar
OS name:�������� Windows 2000
OS architecture: x86
OS version:����� 5.0
Java user name:� Administrator
Java user home:� C:\Documents and Settings\Administrator
Java user dir:�� D:\cloudscape_derby\test
--------- Derby Information --------
[D:\cloudscape_derby\lib\derby.jar] 10.0.2.1 - (56458)
[D:\cloudscape_derby\lib\derbynet.jar] 10.0.2.1 - (56458)
[D:\cloudscape_derby\lib\derbytools.jar] 10.0.2.1 - (56458)
------------------------------------------------------
----------------- Locale Information -----------------
------------------------------------------------------
Each�of the three executions�appear to take less than 1ms so I don't
know how long it is really taking to execute the functions but these
functions should probably be produced�with 'switch' statements like
many of the other functions in this file are.
�
Preparation time for the 'insert' statement averages about 250ms.
Inserting 100 records with:
�
��� for (int i = 0; i < 100; i++)
��� {
����� pstmt.setInt(1, i);
����� lStart = System.currentTimeMillis();
����� pstmt.execute();
����� lEnd�� = System.currentTimeMillis();
����� System.out.println(i + " " + (lEnd - lStart));
��� }
averages about 16ms for each of the 1st 30 records and then about
266ms for each of the remaining 70 records.
�
�