Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > JVM optimization

Reply
Thread Tools

JVM optimization

 
 
ilkinulas
Guest
Posts: n/a
 
      05-09-2005
Hi,
two functions test1 and test2 does the same thing but test2 performs
nearly 20 times better than test1. JVM is unable to optimize the code
in test1. is there a way to tell the java virtual machine to do this
kind of optimization at compile time or runtime?
NOTE : we are using Log4J and java version "1.4.2_02"
private static final Logger log = Logger.getLogger(DebugTest.class);

--------------------------------------------------------------------------

public void test1() {
for (int i = 0; i < 10000000;i++) {
String s ="test"+i;
if(log.isDebugEnabled()) {
log.debug(s);
}
}
}

public void test2() {
for (int i = 0; i < 10000000;i++) {
if(log.isDebugEnabled()) {
String s ="test"+i;
log.debug(s);
}
}
}
--------------------------------------------------------------------------

 
Reply With Quote
 
 
 
 
Thomas Schodt
Guest
Posts: n/a
 
      05-09-2005
ilkinulas wrote:

> two functions test1 and test2 do

almost
> the same thing but test2 performs
> nearly 20 times better than test1. JVM is unable to optimize the code
> in test1. is there a way to tell the java virtual machine to do this
> kind of optimization at compile time or runtime?


You can tell the programmer to read the docs
<http://logging.apache.org/log4j/docs/manual.html#performance>
 
Reply With Quote
 
 
 
 
bugbear
Guest
Posts: n/a
 
      05-09-2005
ilkinulas wrote:
> Hi,
> two functions test1 and test2 does the same thing but test2 performs
> nearly 20 times better than test1.


What - even if if(log.isDebugEnabled()) returns true?

> JVM is unable to optimize the code
> in test1. is there a way to tell the java virtual machine to do this
> kind of optimization at compile time or runtime?
> NOTE : we are using Log4J and java version "1.4.2_02"
> private static final Logger log = Logger.getLogger(DebugTest.class);
>
> --------------------------------------------------------------------------
>
> public void test1() {
> for (int i = 0; i < 10000000;i++) {
> String s ="test"+i;
> if(log.isDebugEnabled()) {
> log.debug(s);
> }
> }
> }
>
> public void test2() {
> for (int i = 0; i < 10000000;i++) {
> if(log.isDebugEnabled()) {
> String s ="test"+i;
> log.debug(s);
> }
> }
> }
> --------------------------------------------------------------------------
>


The compiler has no way of knowing how "likely", let alone
constant, the result of method log.isDebugEnabled().

The reason *you* can optimise this is because you have
knowledge the compiler does not.

BugBear
 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      05-09-2005
bugbear wrote:

> The compiler has no way of knowing how "likely", let alone
> constant, the result of method log.isDebugEnabled().
>
> The reason *you* can optimise this is because you have
> knowledge the compiler does not.


This isn't quite entirely correct, although it's probably close enough for the
OP's purposes.

The runtime JITer /could/, in theory, analyse log.isDebugEnabled() and
determine that it would always return false (E.g. if it inlined it to an access
of a static boolean field that was declared final, or which it could "see" was
never written to). In that case, and if it could further determine that "s"
was not used elsewhere, and that the StringBuilder manipulations involved in
"test"+i had no side-effects, then it would be justified in removing that code.

The "server" JVM from Sun is certainly capable of performing that /kind/ of
optimisation. I don't know whether it would actually do so in this particular
case.

Note, BTW, that if this code was compiled with a version of javac before 1.5,
or compiled for a pre-1.5 platform, then "test"+i would be compiled into
StringBuffer manipulation, rather than StringBuilder. In that case it is /not/
true that "test"+1 has no side-effects (since it involves crossing a
synchronisation barrier), so I wouldn't expect the JITer to be able to remove
it (unless it was buggy, or "knew" that synchronisation barriers didn't matter
for the particular code it generated for the particular machine it was running
on).

To the OP: in general there is no way of telling the runtime that you want it
to perform any particular optimisation -- other than doing it yourself by
changing the code. Any particular JVM implementation /may/ have options to do
so, but I don't know of any, and in any case it would be extremely obscure, and
probably unsupported.

-- chris




 
Reply With Quote
 
Tim Tyler
Guest
Posts: n/a
 
      05-09-2005
ilkinulas <(E-Mail Removed)> wrote or quoted:

> two functions test1 and test2 does the same thing but test2 performs
> nearly 20 times better than test1. JVM is unable to optimize the code
> in test1. is there a way to tell the java virtual machine to do this
> kind of optimization at compile time or runtime?
> NOTE : we are using Log4J and java version "1.4.2_02"
> private static final Logger log = Logger.getLogger(DebugTest.class);
>
> --------------------------------------------------------------------------
>
> public void test1() {
> for (int i = 0; i < 10000000;i++) {
> String s ="test"+i;
> if(log.isDebugEnabled()) {
> log.debug(s);
> }
> }
> }
>
> public void test2() {
> for (int i = 0; i < 10000000;i++) {
> if(log.isDebugEnabled()) {
> String s ="test"+i;
> log.debug(s);
> }
> }
> }
> --------------------------------------------------------------------------


There are a number of class file optimesers available that optimise
after compilation.

http://www.geocities.com/marcoschmid...ptimizers.html

....has a list.

Whether any of them will deal with your example, I don't know -
and the answer may depend on what log.isDebugEnabled() actually does.
--
__________
|im |yler http://timtyler.org/ http://www.velocityreviews.com/forums/(E-Mail Removed) Remove lock to reply.
 
Reply With Quote
 
ilkinulas
Guest
Posts: n/a
 
      05-09-2005
we assume that log.isDebugEnabled returns "false" every time.

if the tests are executed under jvm version 1.5, than test1 and test2
give almost the same results.
is it possible for a virtual machine to prepare the String s just
before it needs it.
i mean "test"+i; is calculated not in line 3 but before log.debug(s),
if log debug is enabled.
1 public void test1() {
2 for (int i = 0; i < 10000000;i++) {
3 String s ="test"+i;
4 if(log.isDebugEnabled()) {
5
6 log.debug(s);
7 }
8 }
9 }

 
Reply With Quote
 
Lee Fesperman
Guest
Posts: n/a
 
      05-09-2005
Chris Uppal wrote:
>
> Note, BTW, that if this code was compiled with a version of javac before 1.5,
> or compiled for a pre-1.5 platform, then "test"+i would be compiled into
> StringBuffer manipulation, rather than StringBuilder. In that case it is /not/
> true that "test"+1 has no side-effects (since it involves crossing a
> synchronisation barrier), so I wouldn't expect the JITer to be able to remove
> it (unless it was buggy, or "knew" that synchronisation barriers didn't matter
> for the particular code it generated for the particular machine it was running
> on).


A smart JIT could know that the StringBuffer object was local and its reference wasn't
passed to an external method. I would guess JIT would do 'variable' usage analysis of
this type. The machine architecture wouldn't matter. I know of one JIT that discovers if
a reference's lifetime is local and allocates it on the stack.

--
Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com)
================================================== ============
* The Ultimate DBMS is here!
* FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
 
Reply With Quote
 
Kevin McMurtrie
Guest
Posts: n/a
 
      05-10-2005
In article <(E-Mail Removed). com>,
"ilkinulas" <(E-Mail Removed)> wrote:

> Hi,
> two functions test1 and test2 does the same thing but test2 performs
> nearly 20 times better than test1. JVM is unable to optimize the code
> in test1. is there a way to tell the java virtual machine to do this
> kind of optimization at compile time or runtime?
> NOTE : we are using Log4J and java version "1.4.2_02"
> private static final Logger log = Logger.getLogger(DebugTest.class);
>
> --------------------------------------------------------------------------
>
> public void test1() {
> for (int i = 0; i < 10000000;i++) {
> String s ="test"+i;
> if(log.isDebugEnabled()) {
> log.debug(s);
> }
> }
> }
>
> public void test2() {
> for (int i = 0; i < 10000000;i++) {
> if(log.isDebugEnabled()) {
> String s ="test"+i;
> log.debug(s);
> }
> }
> }
> --------------------------------------------------------------------------



Do you mean that log.isDebugEnabled() returns false? If so it's totally
your fault for test1 being slower.

This:
String s ="test"+i;

Compiles to:
String s= new StringBuffer("test").append(i).toString();

Lots of code is hidden in such a simple expression. It is beyond the
scope of the compiler to determine whether or not there are side effects
in all of that. It can not omit its execution simply because the result
is not used.
 
Reply With Quote
 
ilkinulas
Guest
Posts: n/a
 
      05-10-2005
if i have a method for logging like this:

public void debug(String s) {
if (log.isDebugEnabled()) {
log.debug(s);
}
}

i would like to use method "debug" in this way
debug("test" + someVariable);
String s is constructed before checking "if debug is enabled". if debug
is not enabled there is no need to concatenate "test" + someVariable.

 
Reply With Quote
 
Thomas Schodt
Guest
Posts: n/a
 
      05-10-2005
ilkinulas wrote:
> if i have a method for logging like this:
>
> public void debug(String s) {
> if (log.isDebugEnabled()) {
> log.debug(s);
> }
> }
>
> i would like to use method "debug" in this way
> debug("test" + someVariable);
> String s is constructed before checking "if debug is enabled". if debug
> is not enabled there is no need to concatenate "test" + someVariable.
>


You could do something like

// covers scalar primitives; byte,char,short,int,long
public void debug(String s,long l) {
if (!log.isDebugEnabled()) return;
log.debug(s+l);
}

public void debug(String s,boolean b) {
if (!log.isDebugEnabled()) return;
log.debug(s+b);
}

// covers the rest - might even cover primitives in 1.5 ?
public void debug(String s,Object o) {
if (!log.isDebugEnabled()) return;
log.debug(s+o.toString());
}

You can add as many debug() variants as you care to.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Zero Optimization and Sign Optimization??? Ravikiran C Programming 22 11-24-2008 03:19 AM
BIOS Optimization Guide Rev. 8.21 Silverstrand Front Page News 0 08-24-2005 01:46 PM
MS JVM and Sun JVM problem Young-Jin Lee Java 3 01-21-2004 04:25 AM
Different behavior for newStringUTF() for Sun JVM and IBM Jvm Lasse Java 1 01-05-2004 07:49 PM
Re: Handling both MS JVM and Sun JVM Kevin Hooke Java 2 09-02-2003 05:31 AM



Advertisments