JetBrains-Research / viktor

Efficient f64-only ndarray in Kotlin
MIT License
125 stars 6 forks source link

NoClassDefFoundError when running under Docker / Kubernetes #27

Closed kristian-elder closed 4 years ago

kristian-elder commented 4 years ago

While I'm able to run our application locally, and test using Viktor also run and pass on our build servers (Linux on CircleCi), I am unable to use the library in our cloud environment.

Unexpected error occurred in scheduled task.","stack_trace":"j.l.NoClassDefFoundError: Could not initialize class org.jetbrains.bio.viktor.Loader
  at o.j.b.v.F64DenseFlatArray$Companion.create$viktor(F64DenseFlatArray.kt:35)
  at o.j.b.v.F64FlatArray$Companion.invoke$viktor(F64FlatArray.kt:373)
  at o.j.b.v.F64FlatArray$Companion.invoke$viktor$default(F64FlatArray.kt:368)
  at o.j.b.v.F64Array$Companion.invoke(F64Array.kt:1105)
...

This is using 1.0.0 of Viktor under Oracle Java 8, in Docker under Kubernetes in Google Cloud (GKE). I am getting no further details in the logs or stdout from the process.

Are there any known issues running Viktor in Docker or other forms of virtualisation?

dievsky commented 4 years ago

No, we've never encountered any virtualisation-specific problems with viktor, but we are certainly interested to learn whether those exist (and fix them). Could you share more information about your setup? Dockerfile, build script, the part of code that calls viktor? That should make the issue easier to reproduce, at the very least.

kristian-elder commented 4 years ago

Actually this issue turn out not to be caused by the virtualized environment at all and was only obscured locally as my test cases where on small lists, and as such did not attempt to load the SIMD enhancements.

The problem rather is an issue with log4j. Viktor uses log4j (which is not a problem) but our environment is using a log4j over slf4j bridge. The compatibility implementation of "ConsoleAppender" in this library does not have a constructor that accepts a layout, and as such it blows up when executing line 57 of Loader.kt.

Is there a reason this is explicitly adding an appender? I would personally much prefer it to go through our bridge as that is already set up with structured JSON logging for our cloud deployment.

dievsky commented 4 years ago

Hey, thank you so much for this follow-up! Actually, I did have some doubts about using log4j in a library, and now they have been justified.

From what I read, a good course of action for viktor (and libraries in general) is to use slf4j interface instead of log4j implementation, as this lets the users choose an implementation themselves and also avoids the kind of problems that you've encountered.

Do you think that transitioning viktor to slf4j would solve your issue?

kristian-elder commented 4 years ago

Thank you!

In our case, using slf4j would be perfect as that's what we're using ourselves, or even using the log4j interfaces but without the dependency on its implementation, e.g. I would expect configuring appenders to be an application concern, not done by a library.

dievsky commented 4 years ago

So, I've just published version 1.0.1 which uses slf4j instead of log4j. Could you try upgrading to this new version and see whether that solves your issue?

kristian-elder commented 4 years ago

Many thanks for a quick resolution, I can confirm that 1.0.1 is indeed working for us.

dievsky commented 4 years ago

That's great to hear!

Can I ask you (out of pure curiosity) how long have you been using viktor and how did you become aware of it?

kristian-elder commented 4 years ago

For now are requirements are very basic and do not actually require the performance of Viktor, I came across it by looking for Kahan sum implementations in Kotlin/Java after we'd identified some issues with numerical instability in sums.

We do have some domains of numerical optimisation within our code base where the capabilities of Viktor may add more significant value in the future.