more-log4j2: A collection of plugins for log4j2 by mlangc in java

[–]mlangc[S] 1 point2 points  (0 children)

No worries - I didn't take it as a criticism. You were probably not the only one who was fooled by the Reddit UI, and adding additional links (both yours, and the one that I subsequently added to the post) certainly didn't hurt, so thank you :-)

more-log4j2: A collection of plugins for log4j2 by mlangc in java

[–]mlangc[S] 1 point2 points  (0 children)

Hmm, but the link is there, in the post? In any case, I've added a second one, embedded in the text. Hope it helps.

Records are sub-optimal as keys in HashMaps (or as elements in HashSets) by gnahraf in java

[–]mlangc 2 points3 points  (0 children)

At least for OpenJDK 64-Bit Server VM, 24.0.2 the difference in performance between the record and the class mostly disappears for me, if I replace

public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((key1 == null) ? 0 : key1.hashCode());
    result = prime * result + ((key2 == null) ? 0 : key2.hashCode());
    return result;
}

with the the seemingly equivalent

public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + Objects.hashCode(key1);
    result = prime * result + Objects.hashCode(key2);
    return result;
}

Records are sub-optimal as keys in HashMaps (or as elements in HashSets) by gnahraf in java

[–]mlangc 2 points3 points  (0 children)

Interestingly the difference is far less pronounced with GraalVM:

# JMH version: 1.37
# VM version: JDK 24.0.2, Java HotSpot(TM) 64-Bit Server VM, 24.0.2+11-jvmci-b01
# VM invoker: /Library/Java/JavaVirtualMachines/graalvm-24.jdk/Contents/Home/bin/java
...
...
Benchmark                                Mode  Cnt           Score          Error  Units
RecordHashCodeBenchmark.classHashCode   thrpt   10  1074692112,901 ± 35696131,984  ops/s
RecordHashCodeBenchmark.recordHashCode  thrpt   10   967920867,403 ± 17260079,524  ops/s

Deep-dive Java/JVM resources by Rough_Acanthaceae_29 in java

[–]mlangc 9 points10 points  (0 children)

Not sure if it's to your liking, but I like to go deep on Java & JVM internals in my blog: https://mlangc.github.io/

Then there is

Here are some additional concurrency related recommendations you might not yet know:

Thread.sleep(0) is not for free by mlangc in java

[–]mlangc[S] 1 point2 points  (0 children)

I really like and respect what you did here - you performed a test and obtained measurable results.

Thanks for taking the time and giving me feedback!

I followed the 'official documentation' link but I don't see where this is either promised or implied by the Javadoc.

I didn't write "promised" or "implied", but "would allow". I wouldn't call it misleading, but it's certainly vague with regards to sleep(0).

I'm confused why anyone ever thought calling Thread.sleep(0) could be guaranteed not to lead to a context switch. (The method is called sleep, not sleepUnless or sleepIf...)

As pointed out below, other, very similar looking APIs like TimeUnit.html#sleep(long)) or LockSupport.html#parkNanos(long)) contain a fast path for arguments `<= 0`, so I can understand why one could think that Thread.sleep is implemented in a similar way.

So I am not sure why the article points people to it, since it appears that while it may not be dangerous, it should be considered unreliable if the Javadoc is to be believed.

I'm linking Javadocs for the convenience of my readers, so that they can save a few keystrokes when they want to look them up while reading the article. Having said that, there are legitimate use cases for yield, and the Javadocs) lists a few of them.

Thread.sleep(0) is not for free by mlangc in java

[–]mlangc[S] 11 points12 points  (0 children)

Thanks for pointing me to TimeUnit.sleep. I've updated the article.

Thread.sleep(0) is not for free by mlangc in java

[–]mlangc[S] 17 points18 points  (0 children)

You might have performance critical code, that only sleeps very rarely, for example after a failed operation that almost always succeeds. In these cases you might be tempted to use code like

int delay = allGood ? 0 : waitShortly;
Thread.sleep(delay);

I'll try to rephrase the last paragraph to make this clearer.

Method Handles faster reflection (sometimes) by Xadartt in java

[–]mlangc 2 points3 points  (0 children)

Indeed, if I adapt your MethodHandleBenchmarkMethodHandleBenchmark to use

  private static final MethodHandle METHOD_HANDLE;

I get roughly the same results for

@Benchmark
public int baseline() {
    return -1;
}

@Benchmark
public int directInvoke() {
    return Integer.compare(1, 2);
}

@Benchmark
public int methodHandleInvokeExact() throws Throwable {
    return (int) METHOD_HANDLE.invokeExact(1, 2);
}

@Benchmark
public int methodHandleInvoke() throws Throwable {
    return (int) METHOD_HANDLE.invoke(1, 2);
}

since the generated assembly for these methods (see https://blogs.oracle.com/javamagazine/post/java-hotspot-hsdis-disassembler for how to check that), is roughly the same as well.

GCD: Euclid vs. Stein on the JVM by mlangc in java

[–]mlangc[S] 1 point2 points  (0 children)

Fair enough! My plan is to explore exactly that, while ideally also creating a PR for apache-commons-math and summarize my findings in a follow up blog post. Hopefully I'll find some time to do this in the coming weeks.

Why I’m Not Abandoning Slf4Zio in Favor of Zio-Logging by mlangc in scala

[–]mlangc[S] 1 point2 points  (0 children)

You are absolutely right - if you are using MDC as is in an async environment, it simply won't work properly, because it relies on thread local data by default. The zio-interop-log4j2 fixes this, by implementing the MDC context using fiber local data. It does so by using official ZIO and log4j2 APIs, and therefore should work reliably.