Well, after digging deeper it seems it didn’t really pass on Java 16. The 
allocation instrumenter was unable to instrument anything so it didn’t generate 
the errors the test looks for. I tried with Java 12-14 and those all failed. In 
Java 15 the JVM crashed.

Ralph

> On Apr 7, 2021, at 11:33 PM, Ralph Goers <ralph.go...@dslextreme.com> wrote:
> 
> Interesting. I ran the test with
> 
> openjdk version "16" 2021-03-16
> OpenJDK Runtime Environment (build 16+36-2231)
> OpenJDK 64-Bit Server VM (build 16+36-2231, mixed mode, sharing)
> 
> and it passed. I then ran it with 
> 
> openjdk version "11.0.2" 2019-01-15
> OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
> OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
> 
> and
> 
> java version "11.0.9" 2020-10-20 LTS
> Java(TM) SE Runtime Environment 18.9 (build 11.0.9+7-LTS)
> Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.9+7-LTS, mixed mode)
> 
> and
> 
> java version "11.0.10" 2021-01-19 LTS
> Java(TM) SE Runtime Environment 18.9 (build 11.0.10+8-LTS-162)
> Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.10+8-LTS-162, mixed mode)
> 
> and it failed with all of them.
> 
> Ralph
> 
> 
>> On Apr 6, 2021, at 3:22 PM, Ralph Goers <ralph.go...@dslextreme.com 
>> <mailto:ralph.go...@dslextreme.com>> wrote:
>> 
>> I am using 
>> 
>> openjdk version "11.0.10" 2021-01-19 LTS
>> OpenJDK Runtime Environment Corretto-11.0.10.9.1 (build 11.0.10+9-LTS)
>> OpenJDK 64-Bit Server VM Corretto-11.0.10.9.1 (build 11.0.10+9-LTS, mixed 
>> mode)
>> 
>> Our test uses
>> <dependency>
>> <groupId>com.google.code.java-allocation-instrumenter</groupId>
>> <artifactId>java-allocation-instrumenter</artifactId>
>> <version>3.3.0</version>
>> </dependency>
>> to validate that it is not allocating any objects.
>> 
>> If you want to test it yourself you can do
>> 
>> git clone https://github.com/apache/logging-log4j2.git 
>> <https://github.com/apache/logging-log4j2.git> 
>> <https://github.com/apache/logging-log4j2.git 
>> <https://github.com/apache/logging-log4j2.git>>
>> cd logging-log4j2
>> mvn -DskipTests=true clean install
>> cd log4j-core
>> mvn surefire:test -Dtest=GcFreeSynchronousLoggingTest 
>> -Dmaven.surefire.debug="-Dlog4j2.usePreciseClock=true”
>> 
>> When it fails you will see a strange message with 
>> 
>> I just allocated the object 2021-04-06T21:55:20.878377Z of type 
>> java/time/Instant whose size is 24 ==> expected: <true> but was: <false>
>> 
>> Ralph
>> 
>>> On Apr 6, 2021, at 9:53 AM, Peter Levart <peter.lev...@gmail.com> wrote:
>>> 
>>> Hi Ralph,
>>> 
>>> 
>>> Which version of JDK did you try running the code. I tried the following 
>>> benchmark:
>>> 
>>> 
>>> @BenchmarkMode(Mode.AverageTime)
>>> @Fork(value = 1)
>>> @Warmup(iterations = 5, time = 1)
>>> @Measurement(iterations = 10, time = 1)
>>> @OutputTimeUnit(TimeUnit.NANOSECONDS)
>>> @State(Scope.Benchmark)
>>> public class InstantBench {
>>> 
>>>   @Benchmark
>>>   public long epochMilli() {
>>>       Instant instant = Clock.systemUTC().instant();
>>>       return instant.toEpochMilli();
>>>   }
>>> }
>>> 
>>> 
>>> And didn't get any heap allocation on either JDK 11:
>>> 
>>> 
>>> Benchmark Mode  Cnt   Score    Error   Units
>>> InstantBench.epochMilli                      avgt   10  34.722 ±  0.328   
>>> ns/op
>>> InstantBench.epochMilli:·gc.alloc.rate       avgt   10  ≈ 10⁻⁴           
>>> MB/sec
>>> InstantBench.epochMilli:·gc.alloc.rate.norm  avgt   10  ≈ 10⁻⁵             
>>> B/op
>>> InstantBench.epochMilli:·gc.count            avgt   10     ≈ 0           
>>> counts
>>> 
>>> 
>>> ..nor on JDK 16:
>>> 
>>> 
>>> Benchmark Mode  Cnt   Score    Error   Units
>>> InstantBench.epochMilli                      avgt   10  33.612 ±  0.258   
>>> ns/op
>>> InstantBench.epochMilli:·gc.alloc.rate       avgt   10  ≈ 10⁻⁴           
>>> MB/sec
>>> InstantBench.epochMilli:·gc.alloc.rate.norm  avgt   10  ≈ 10⁻⁵             
>>> B/op
>>> InstantBench.epochMilli:·gc.count            avgt   10     ≈ 0           
>>> counts
>>> 
>>> 
>>> Regards, Peter
>>> 
>>> On 4/6/21 8:17 AM, Ralph Goers wrote:
>>>> Yes, I am aware that the Instant is constructed from the two values. That 
>>>> is exactly why I was hoping I could pass in an object where the values of 
>>>> those two fields could be injected. This would still allow Instant to be 
>>>> immutable but allow Log4j to update one of the pre-existing Clock 
>>>> instances it is managing. That would require that a new Interface be 
>>>> defined with the two set methods and a new static method in the Clock 
>>>> class.
>>>> 
>>>> Getting the value in microseconds would probably be a middle ground that 
>>>> could also work considering that is the best resolution available on most 
>>>> hardware today.
>>>> 
>>>> Whichever is implemented I suspect getting it back ported to Java 11 is 
>>>> unlikely? According to the surveys I’ve seen the majority of users are 
>>>> still on Java 8. Given that, I’d be surprised if there is a mad rush to 
>>>> adopt Java 17 very soon. Given where things are I’m not even sure how 
>>>> likely it is this could make it in for Java 17.  The irony here is that 
>>>> the folks who need to run garbage free are also the ones most likely to 
>>>> need a Clock with higher resolution. Right now they can’t have both.
>>>> 
>>>> Ralph
>>>> 
>>>>> On Apr 5, 2021, at 1:26 PM, Roger Riggs <roger.ri...@oracle.com> wrote:
>>>>> 
>>>>> Hi,
>>>>> 
>>>>> Java does not have a data type with enough resolution to hold a full 
>>>>> nanosecond value.
>>>>> Hence the implementation of Instant holding seconds and nanos.
>>>>> 
>>>>> There is an long dormant enhancement request to return micro-seconds as a 
>>>>> long.
>>>>> 8196003 <https://bugs.openjdk.java.net/browse/JDK-8196003> java.time 
>>>>> Instant and Duration methods for microseconds
>>>>> 
>>>>> That might be useful if the application gets enough resolution from 
>>>>> microseconds.
>>>>> There might be some clever interpolation between 
>>>>> System.currentTimeMillis()
>>>>> and adjusting with System.nanoTime().
>>>>> Though it would likely not be exactly synchronized with the values from 
>>>>> Instant.
>>>>> 
>>>>> Regards, Roger
>>>>> 
>>>>> 
>>>>> On 4/5/21 3:56 PM, Brian Goetz wrote:
>>>>>> Project Valhalla will allow Instant to be migrated to a primitive class, 
>>>>>> which would address your problem.
>>>>>> 
>>>>>> On 4/2/2021 7:47 PM, Ralph Goers wrote:
>>>>>>> Log4j 2 supports the notion of a PreciseClock - one that can be 
>>>>>>> initialized to something more precise than a millisecond. At the same 
>>>>>>> time it also supports running with no heap allocations in certain 
>>>>>>> circumstances. I am in the process of moving our master branch to 
>>>>>>> require Java 11 as the minimum. In doing so I am encountering unit test 
>>>>>>> errors while verifying that logging is garbage free. They all occur 
>>>>>>> allocating an Instant.
>>>>>>> 
>>>>>>> The code we have simply does
>>>>>>> 
>>>>>>> public void init(MutableInstant mutableInstant) {
>>>>>>>    Instant instant = java.time.Clock.systemUTC().instant();
>>>>>>> mutableInstant.initFromEpochSecond(instant.getEpochSecond(), 
>>>>>>> instant.getNano());
>>>>>>> }
>>>>>>> In our previous tests we had thought the allocation was being 
>>>>>>> eliminated due to escape analysis since the data is being extracted 
>>>>>>> from the Instant and not passed along. However, after upgrading the 
>>>>>>> Google test library and the JDK version it appears that is not the case.
>>>>>>> Ideally we would really like something like
>>>>>>> 
>>>>>>> public void init(MutableInstant mutableInstant) {
>>>>>>>       java.time.Clock.systemUTC().initInstant(mutableInstant);
>>>>>>> }
>>>>>>> 
>>>>>>> where Mutable instant would implement an interface that has the two set 
>>>>>>> methods.The method would execute the same logic that is in the 
>>>>>>> instant() method but instead of creating a new Instant it would call 
>>>>>>> the set methods for the provided object.
>>>>>>> 
>>>>>>> This would allow us to either have the MutableInstants in ThreadLocals 
>>>>>>> or some other mechanism to ensure they are thread safe and have no heap 
>>>>>>> allocations. As it stands now I see no way to gain access to the higher 
>>>>>>> precision clock without memory allocation.
>>>>>>> 
>>>>>>> Do you know of another way to do this? Am I missing something?
>>>>>>> 
>>>>>>> Ralph

Reply via email to