[JAVA-4402] Load Zstandard library during connection creation time Created: 10/Nov/21  Updated: 27/Oct/23  Resolved: 15/Nov/21

Status: Closed
Project: Java Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Unknown
Reporter: Halil İbrahim Şener Assignee: Valentin Kavalenka
Resolution: Works as Designed Votes: 1
Labels: external-user
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Currently, the Zstandard library loading only happens when ZstdCompressor#compress is called. This can be problematic when the caller thread cannot do a blocking call. In our case, it's Netty's event loop thread, and BlockHound throws a BlockingOperationError.

Instead, we can load the class when the ZstdCompressor instance is created.



 Comments   
Comment by Halil İbrahim Şener [ 23/Nov/21 ]

Thanks for the detailed answer @Valentin Kavalenka.

I don't expect a performance impact since it needs to happen only once. However, I like doing it eagerly to ensure the MongoDB driver will work with Zstd (otherwise, fail fast). Does that make sense?

As you said, the error from BlockHound can also be solved by adding a rule. OTOH, this can also be an argument to ensure the blocking call happens on a specific thread on the MongoDB driver side rather than having N MongoDB customers add the rule.

Comment by Valentin Kavalenka [ 15/Nov/21 ]

Hi halil.sener@teampicnic.com,

One indeed must not regularly do blocking calls in a Netty event loop thread, because doing so wastes the thread by preventing it from doing other operations that may be ready. However, doing a finite number of blocking operations in such a thread is what one may call lazy initialization, and it affects performance characteristics in the same way regardless of whether being done in an event loop thread or not. Besides lazy class/interface initialization, which the PR proposes to do eagerly for the Zstd class because it involves a blocking operation, there is lazy resolution of symbolic references to a class/interface (see JLS 12.3, JVMS 5.4.3.1), which may result in loading a class/interface lazily, which is also usually a blocking operation. That is, there is always a possibility that a thread in a Java application may do implicit blocking operations (loading classes lazily) without an engineer being aware of it or a tool like BlockHound detecting such a possibility.

We think that the proposed change should only be done based on reports that laziness negatively affects performance characteristics of an application. So far there have been no such reports. Regarding the complaint from BlockHound, it seems one can allow blocking calls inside a method. In your case, you probably can allow blocking operations inside the ZstdCompressor.compress method, or customize the blocking method callback such that it does not report an error if the call stack contains frames for ZstdCompressor.compress and Native.load.

Comment by Esha Bhargava [ 11/Nov/21 ]

halil.sener@teampicnic.com Thank you for reporting the issue! We'll look into it and get back to you soon.

Comment by Halil İbrahim Şener [ 11/Nov/21 ]

I created https://github.com/mongodb/mongo-java-driver/pull/821.

Generated at Thu Feb 08 09:01:58 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.