As to why it still creates garbage even if you do not touch the
arguments in the testWithout method, I would guess that different
inlining rules apply to large methods, small methods and methods that
are already inlined within other methods.

To give definitive answer I'll have to look through the opto assembly
which will take me a couple of hours.  There was something in the
-XX:+LogCompilation output but that's just a hint.  To get to the
truth you need the assembly code.

Back to the original issue....

Some kind of automated post-processing can be set up that cause
compilation errors if anything other than LOG.log is used inside of an
if (isLoggable) predicate.  I've seen an example where AspectJ can be
set up to trigger compilation errors every time it encounters a
System.out and System.err reference.  I'm sure there are many
solutions, some even integrate with IDEs.

On Fri, Mar 23, 2012 at 11:02 PM, Zlatin Balevsky <zlatinb at gmail.com> wrote:
> Your test has nothing to do with stack allocation because you never
> use the objects that you pass to the log_info method so JIT removes
> them. ?Apply the following patch and see yourself create garbage in
> both testWith and testWithout.
>
> --- Test2.java ?2012-03-23 23:01:05.540475497 -0400
> +++ Test.java ? 2012-03-23 23:01:47.304477562 -0400
> @@ -6,8 +6,11 @@
> ? final Object existing = new Object();
> ? Object tmp = null;
>
> + ?long sideEffect;
> ? public void log_info(String format, Object ... args) {
> ? ? if (log_level) {
> + ? ? ?for (Object o : args)
> + ? ? ? sideEffect += o.hashCode();
> ? ? ? System.out.println("don't optimise me out");
> ? ? }
> ? }
> @@ -88,11 +91,8 @@
> ? ? printSummary("with alloc", res[0], "w/o alloc", res[1]);
> ? ? printSummary("with alloc", res[2], "w/o alloc", res[3]);
> ? ? printSummary("with alloc", res[4], "w/o alloc", res[5]);
> - ? ?System.out.println("---- with stack allocation and \"real use case\"");
> - ? ?res = testWithOtherCode(z);
> - ? ?printSummary("log only", res[0], "log+work", res[1]);
> - ? ?printSummary("log only", res[2], "log+work", res[3]);
> - ? ?printSummary("log only", res[4], "log+work", res[5]);
> +
> + ? ?System.out.println(sideEffect);
> ? }
>
> ? public static void main(String[] args) {
>
>
> On Fri, Mar 23, 2012 at 10:48 PM, Ximin Luo <infinity0 at gmx.com> wrote:
>> On 24/03/12 02:44, Zlatin Balevsky wrote:
>>> Wrong. ?Extracting the log statement into its own method and calling
>>> that method inside the while loop still creates garbage. ?Stack frames
>>> are different.
>>>
>>
>> How do you explain the results obtained from running my test code, then? Turn
>> on -verbose:gc. testWithStackAllocation results in no GC,
>> testWithoutStackAllocation results in lots of GC.
>>
>>> Read again exactly how Escape Analysis works. ?The objects it prevents
>>> from creating do not appear in heap histograms. ?Take a "jmap -histo
>>> <pid>" and you will see a huge number of java.lang.Integer objects in
>>> the heap, not on the stack.
>>>
>>
>> If you're still talking about your example, this is exactly consistent with 
>> my
>> explanation, i.e. that escape analysis is NOT occurring, properly anyway.
>>
>>> The difference in run times of your example could be due to many
>>> things. ?How many iterations did you run? ?It may be still in
>>> interpreted mode. ?Enable -XX:+PrintCompilation and discard any
>>> results until JIT stops printing.
>>
>> Done that, JIT stops printing after the 3rd iteration and results are the 
>> same
>> thereafter.
>>
>> --
>> GPG: 4096R/5FBBDBCE
>> https://github.com/infinity0
>> https://bitbucket.org/infinity0
>> https://launchpad.net/~infinity0
>>
>>
>> _______________________________________________
>> Devl mailing list
>> Devl at freenetproject.org
>> https://emu.freenetproject.org/cgi-bin/mailman/listinfo/devl

Reply via email to