Earlier quoted context omitted.
Desktop - that's my complaint... you wrote that the code samples "barely fit on desktop", which is only true because your CSS wastes over 2/3rds of the screen width I have provided to my user agent. (it's fine though - I use Reader Mode on such user-hostile sites)
Oh yeah, now I understand. I'm struggling to find a width for the layout that makes sense for text (where narrow columns are preferable), but also for code snippets (where you want wider columns).
The sorry state of Java deserialization
41–50 of 54 posts
Re: The sorry state of Java deserialization
#42Earlier quoted context omitted.
> Also, hard to say without source code but there is a high chance even more efficient methods like Protobuf create a lot of Java objects and that kills cache locality I don’t think this can be claimed that easily without more info, generational GCs work pretty much like an arena allocator, with very good cache locality (think of an ArrayList getting filled with objects that are continuously allocated in short order.…
GC pressure is another factor. Even in the trivial ownership case, gc:ing in a GB/s allocation environment comes at a cost.
Re: The sorry state of Java deserialization
#43Earlier quoted context omitted.
GC pressure is another factor. Even in the trivial ownership case, gc:ing in a GB/s allocation environment comes at a cost.
Adding Guava testlib's GcFinalization.awaitFullGc() before a benchmark run and -XX:+UseParallelGC, I saw the runtimes decrease by 30s in Bench_Fury_Ordinal and 20s in Bench_ObjectOutputStream. Ideally you would run using JMH to avoid jit warmup issues, previous runs, etc from polluting your results.
In general I'm not a big fan of JMH for testing sustained I/O scenarios, as CPU, OS and storage behavior are extremely relevant, and JMH tends to interfere with access patterns.
Re: The sorry state of Java deserialization
#44Re: The sorry state of Java deserialization
#45I noticed: 1. Small read buffers. No reason to sequentially read and parse gigabytes only 4kb at a time. 2. parseDelimitedFrom created a new CodedInputStream on every message, which has its own internal buffer; that's why you don't see a buffered stream wrapper in the examples. Every iteration of the loop is allocating fresh 4kb byte[]s. 3. The nio protobuf code creates wrappers for the allocated ByteBuffer on every…
But Google must surely have some optimized Java libraries for this given that they use protobufs everywhere.
Edit: I found https://beam.apache.org/releases/javadoc/current/org/apache/... which given it was developed by google is probably close to what they use. I wonder if the logic from this could be pulled out for use with non-distributed workflows.
Re: The sorry state of Java deserialization
#46What's the reason why reading 3GB via duckdb is _faster_ than raw HDD speed? Is it compression/caching?
Re: The sorry state of Java deserialization
#47Earlier quoted context omitted.
Adding Guava testlib's GcFinalization.awaitFullGc() before a benchmark run and -XX:+UseParallelGC, I saw the runtimes decrease by 30s in Bench_Fury_Ordinal and 20s in Bench_ObjectOutputStream. Ideally you would run using JMH to avoid jit warmup issues, previous runs, etc from polluting your results.
Did you dial up to run for 1 billion items? In general I'm not a big fan of JMH for testing sustained I/O scenarios, as CPU, OS and storage behavior are extremely relevant, and JMH tends to interfere with access patterns.
Re: The sorry state of Java deserialization
#48Earlier quoted context omitted.
Author here, I'm away from my computer atm, but I can cook up a repo with each test in a few hours when I get home. I designed the tests as a drag race because that mimics my real world usage.
That's nice - I'd encourage you to play around with attaching e.g. JMC [1] to the process to better understand why things are as they are. I tried recreating your DataInputStream + BufferedInputStream (wrote the 1brc data to separate output files, read using your code - I had to guess at ResultObserver implementation though). On my machine it roughly in the same time frame as yours - ~1min. According to Flight Record…
I would guess at least some of the bottlenecks are in hardware, the operating system or in native code (including the JVM) in this case.
Re: The sorry state of Java deserialization
#49Earlier quoted context omitted.
> Making a header with the city string mapped to an integer would dramatically shrink the file and speed up parsing. Indeed, Parquet will do this for you if you let it. I also wonder how good Java is at optimizing closure creation in a loop, as in: k -> new ResultObserver() The vast majority of those closures are created and never called. C++ might optimize this well if calling a template but has basically no chance…
I believe the term for this is "partial escape analysis" (PEA). GraalVM is the SOTA in the JVM world for this. Here's an oldish blog on this: https://chrisseaton.com/truffleruby/seeing-escape-analysis/ I'm sure PEA is better now, but it's not sure if it's moved beyond scalars (int, float, etc.)
invokedynamic #16, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;Re: The sorry state of Java deserialization
#50Earlier quoted context omitted.
I believe the term for this is "partial escape analysis" (PEA). GraalVM is the SOTA in the JVM world for this. Here's an oldish blog on this: https://chrisseaton.com/truffleruby/seeing-escape-analysis/ I'm sure PEA is better now, but it's not sure if it's moved beyond scalars (int, float, etc.)
Wouldn't the lambda here by always escape? It gets created in the function and passed into another one. Looking at the byte code it looks like it always allocates in when its in the interpreter: invokedynamic #16, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
(One think I like about less heavily JIT-reliant languages is that it can be more obvious when something will incur a runtime cost.)