Earlier quoted context omitted.
I would hope that any reasonably performant implementation would be faster not only than NVMe, but also faster than CPU to RAM data transfers. The AMD EPYC-Milan in the test server supports memory reads at 150 gigabytes/sec, but thats a 32 core machine, and our test only gets 8 of those cores, so we probably can't expect more than 37 gigabytes per second of read bandwidth. The total file is ~12 gigabytes, so we shoul…
> any reasonably performant implementation would be faster not only than NVMe Saturating NVMe bandwidth is wicked hard if you don't know what you're doing. Most people think they're I/O bound because profiling hinted at some read() function somewhere, when in fact they're CPU bound in a runtime layer they don't understand.
The One Billion Row Challenge
281–290 of 366 posts
Re: The One Billion Row Challenge
#282Earlier quoted context omitted.
Only if you validate the UTF-8 as being valid. If you just accept that it is you can treat it as just some bytes. Nothing in the spec I see requires processing UTF-8 as an actual Unicode string. The easiest way to handle Unicode is to not handle it at all, and just shove it down the line. This is often even correct, as long as you don't need to do any string operations on it. If the author wanted to play Unicode game…
Since the tail of the line has a known format I guess we are rescued by the fact that the last 0x3B is the semicolon as the rest is just a decimal number. We can’t know the first 0x3B byte is the semicolon since the place names are only guaranteed to not contain 0x3B but can contain 0x013B. So a parser should start from the rear of the line and read the number up to the semicolon and then it can treat the place name…
I'm no UTF-8 guru, but I think you might be possible to do this sort of a springboard for skipping over multi-byte codepoints, since as far as I understand the upper bits of the first byte encodes the length:
byte utfByte1 = (byte) (val & 0xF0);
if (utfByte1 == (byte) 0xF0) { // 4 byte codepoint
// ignore 3
}
else if (utfByte1 == (byte) 0xE0) { // 3 byte codepoint
// ignore 2
}
else if (utfByte1 == (byte) 0xC0) { // 2 byte codepoint
// ignore 1
}Re: The One Billion Row Challenge
#283Earlier quoted context omitted.
Go for it!
You nerd sniper you! But more seriously, the JVM's support for vector intrinsics is very basic right now, and I think I'd spend far more time battling the JVM to output the code I want it to output than is fun. Java just isn't the right language if you need to superoptimize stuff. Theoretically all of the above is super simple SIMD stuff, but I have a suspicion that SIMD scatter/gather (needed for the state lookup ta…
I still appreciate the intention of seeing how far we can squeeze performance of modern Java+JVM though. Too bad very few folks have the freedom to apply that at their day jobs though.
Re: The One Billion Row Challenge
#284This has been super fun. My current PR[1] is another 15% faster than my entry in the README. Sadly I haven't been able to make any progress on using SIMD to accelerate any part of it. I think the issues with hashing could be easily covered by having the 500 city names in the test data also be randomly generated at test time. There is no way to ensure there aren't hash collisions without doing a complete comparison be…
1 billion rows, 500 unique values... It becomes very possible to find an instance of each unique value, then runtime-design a hash algorithm where those 500 values don't collide. Java allows self modifying code after all (and this challenge also allows native code, which can also be compiled-at-runtime)
Re: The One Billion Row Challenge
#285Should run about 10-20% faster than that on the mentioned Hetzner hardware.
- Since we only do one decimal of floating point precision it uses integer math right from the get-go.
- FNV1-a hash with linear probing and a load factor well under 0.5.
- Data file is mmap’d into memory.
- Data is processed in 8 totally separate chunks (no concurrent data structures) and then those aggregations are in turn aggregated when all threads have finished.
Re: The One Billion Row Challenge
#286I suspect Java is not the fastest language for this. I’d love to see unofficial contenders tackle this challenge using different languages.
I’ve also seen versions in Rust, Go, Python, Clickhouse and DuckDB. The discussions tab on the GitHub repo lists some of these.
Re: The One Billion Row Challenge
#287Earlier quoted context omitted.
I don't have a CS background and when I eventually had to do interviews for Google, "Calculate mean/median/mode of temperatures" was the interview question I went with, intending to avoid BS leetcode* I always worried it was too easy, but I'm heartened by how many comments miss the insight I always looked for and you named: you don't need to store a single thing. I do wonder if it'll work here, at least as simply as…
Streaming calculation of the exact median with no storage at all is non-trivial at best in the general case, and I'm not aware of any way to calculate the mode at all. Any pointers to the methods you used in your interview answers? If you came up with them on the fly, then... well, sign here for your bonus. Can you start Monday?
Re: The One Billion Row Challenge
#288Is there a way to create this file without having java ? This is for use on a BSD where Java may not work too well. Thanks
It’s just the city names + averages from the official repository using a normal distribution to generate 1B random rows.
Re: The One Billion Row Challenge
#289Unfortunately I have no time to code this up but things that I would try to make it fast: - Read with O_DIRECT (but compare it with the mmap approach). I know O_DIRECT gets much hate, but this could be one of the rare cases where it helps. - Use a simple array with sentinel and linear search for the station names. This is dumb, but if the number of stations is small enough this could beat the hash. (In the back of my…