TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

How fast can a BufferedReader read lines in Java?

91 pointsby CCsalmost 6 years ago

15 comments

elFartoalmost 6 years ago
The first issue I can see with that code is it&#x27;s not doing what he expects. He does this to read the file into a StringBuffer:<p><pre><code> bf.lines().forEach(s -&gt; sb.append(s)); </code></pre> However, this ends up reading all the lines into one giant line, since the String&#x27;s that lines() produces have the newline character stripped. This leads to the second lines() call to read a 23MB line (the file produced by gen.py). This is less than optimal.<p>The fastest version I managed to write was:<p><pre><code> public void readString5(String data) throws IOException { int lastIdx = 0; for (int idx = data.indexOf(&#x27;\n&#x27;); idx &gt; -1; idx = data.indexOf(&#x27;\n&#x27;, lastIdx)) { parseLine(data.substring(lastIdx, idx)); lastIdx = idx+1; } parseLine(data.substring(lastIdx)); } </code></pre> Not the prettiest thing, but it went from 0.594 GB&#x2F;s to 1.047 GB&#x2F;s. Also, it doesn&#x27;t quite do the same as the lines() method, but that&#x27;s easily changed.
评论 #20543544 未加载
评论 #20543259 未加载
评论 #20543464 未加载
评论 #20542793 未加载
评论 #20542788 未加载
derefralmost 6 years ago
I don&#x27;t know what Java&#x27;s BufferedReader is doing, but it&#x27;s probably not the optimal thing in terms of IO throughput. I would blame the algorithm long before blaming anything inherent about the JVM.<p>Erlang is another language where &quot;naive&quot; IO is kind of slow. <a href="https:&#x2F;&#x2F;github.com&#x2F;bbense&#x2F;beatwc&#x2F;" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;bbense&#x2F;beatwc&#x2F;</a> is a project someone did to test various methods of doing IO in Erlang&#x2F;Elixir, and their performance for a line-counting task, relative to the Unix wc(1) command.<p>It&#x27;s interesting to see which approaches are faster. Yes, parallelism gains you a bit, but a much larger win comes from avoiding the stutter-stop effect of cutting the read buffer off whenever you hit a newline. Instead, the read buffer should be the same size as your IO source&#x27;s optimal read-chunk size (a disk block; a TCP huge packet), and you should grab a whole buffer-ful of lines at a time, do a <i>pattern-matching binary scan</i> to collect all the indices of the newlines, and then use those indices to part the buffer out as <i>slice references</i>.<p>This achieves quite a dramatic speedup, since most of the time you don&#x27;t need movable copies of the lines, and can copy the line (or more likely just part of it) yourself when you need to hold onto it.<p>This approach is <i>probably</i> also already built in to Java&#x27;s &quot;better&quot; IO libraries, like NIO.
评论 #20542596 未加载
评论 #20542300 未加载
评论 #20542587 未加载
Sindisilalmost 6 years ago
Honestly, it seems that nearly everyone here is missing his point.<p>Some of the blame for that probably lies with his headline choice, but he clearly states at the end of this post:<p>&quot;&quot;&quot; This is not the best that Java can do: Java can ingest data much faster. However, my results suggest that on modern systems, Java file parsing might be frequently processor-bound, as opposed to system bound. That is, you can buy much better disks and network cards, and your system won’t go any faster. Unless, of course, you have really good Java engineers.<p>Many firms probably just throw more hardware at the problem. &quot;&quot;&quot;<p>It&#x27;s not <i>about</i> this piece of code. It&#x27;s not even about Java In the previous post he mentions at the start of this one, he pointed out:<p>&quot;&quot;&quot; These results suggest that reading a text file in C++ could be CPU bound in that sense that buying an even faster disk would not speed up your single-threaded throughput. &quot;&quot;&quot;<p>So, I take his point to be that one shouldn&#x27;t make assumptions about performance. Rough performance scales -- such as have been posted here many times (e.g. [1]) -- make great rules of thumb for implementation choices or as a guide for where to look first for bottlenecks. To optimize in the <i></i>real world<i></i>, though, you&#x27;re best served using <i></i>real measurements<i></i>.<p>[1] <a href="https:&#x2F;&#x2F;www.prowesscorp.com&#x2F;computer-latency-at-a-human-scale&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.prowesscorp.com&#x2F;computer-latency-at-a-human-scal...</a>
评论 #20543918 未加载
znpyalmost 6 years ago
The post does nothing to explain how and why, it just throws a couple of outputs from a non specified machine and does no comparison.<p>It has no baseline and no specs. For all I know, he could have got his 0.5 GB&#x2F;sec on ab old Pentium II processor.<p>There is no analysis.<p>I am perplexed.
评论 #20542306 未加载
tawy12345almost 6 years ago
I&#x27;m amazed at how upset some commenters are about a blog post that did a toy experiment and didn&#x27;t actually make any strong claims.<p>I&#x27;m actually a stickler about good benchmarks - it riles me when people draw sweeping conclusions from poorly-designed experiments. Lemire is actually one of the good ones. If you want something more fully developed than a blog post, read one of his papers.<p>I personally really enjoy his blog because of this - he&#x27;s good at picking interesting exploratory experiments that provide some insight, without trying to over-generalize from the results. If you read his conclusion, the point is that there is a good probability that even relatively simple programs are CPU-bound. His experiment supports that point. My experience also matches that - I&#x27;ve seen a lot of data processing code that could be I&#x2F;O bound in theory (i.e. a perfect implementation could max out CPU or network) but is CPU bound in practice. Usually because of string manipulation, regexes, or any number of other things.<p>&gt; This is not the best that Java can do: Java can ingest data much faster. However, my results suggest that on modern systems, Java file parsing might be frequently processor-bound, as opposed to system bound. That is, you can buy much better disks and network cards, and your system won’t go any faster. Unless, of course, you have really good Java engineers.
评论 #20542752 未加载
ubu7737almost 6 years ago
This is absurd, the original platform libraries do not account for the fastest use-cases in any specialized IO case.<p>Java NIO channel should have been used for this. It was demonstrated back in the early 2000s with the &quot;Grand Canyon&quot; demo achieving very good throughput for its time, and it&#x27;s still the gold standard.
adrianNalmost 6 years ago
So what&#x27;s the reason for this? Is it maybe because of some unicode shenanigans? Java characters are 16bit iirc, and strings have some forty bytes of constant overhead.
评论 #20542253 未加载
评论 #20542475 未加载
评论 #20542268 未加载
vbezhenaralmost 6 years ago
Java has many inefficient parts. For example there&#x27;s no immutable array concept (or owning concept, like in Rust), so there&#x27;s a lot of unnecessary array copies happens in JDK. String is not well designed. There was an attempt to abstract String concept into CharSequence, but a lot of code still uses Strings.<p>I made a similar benchmark. The idea is as follows: we have 2 GB byte array (because arrays in Java have 32 bit limit, LoL) filled with 32..126 values, imitating ASCII text and 13 values imitating newlines.<p>The first test is simply does XOR the whole array. It&#x27;s the ideal result which should correspond to memory bandwidth.<p>The second test wraps this array into ByteArrayInputSteram, converts it into Reader using InputStreamReader with UTF-8 encoding, reads lines using BufferedReader and in the end also XORs every char value.<p>For 2 GB I have 516 ms as an ideal time (3,8 GB&#x2F;s which is still almost order of magnitude less than theoretical 19.2 GB&#x2F;s DDR4 speed) and 3566 ms as a BufferedReader, so you can have almost 7x speed improvement with better implementation.<p>Benchmark: <a href="https:&#x2F;&#x2F;pastebin.com&#x2F;xMD4W8mn" rel="nofollow">https:&#x2F;&#x2F;pastebin.com&#x2F;xMD4W8mn</a>
nullwasamistakealmost 6 years ago
Eh, he didn&#x27;t use NIO. BufferedReader is an ancient Java relic. Like reading from STDIN in c, it&#x27;s not made to be fast, it&#x27;s there for convenience and backwards compatibility.<p>Read a file using something like Vert.X, which is optimized for speed. I&#x27;m 100% confident it will be faster than the naive c approach
评论 #20543203 未加载
评论 #20542377 未加载
tantaloralmost 6 years ago
One thing that jumps out at me is the test code writes to &quot;volume&quot; variable in the read loop, I assume for counting the number of bytes in the file, but never reads it back. A clever compiler will optimize away those writes, the string length check, the loop over the lines, and actually reading the file.<p>I&#x27;m not saying that&#x27;s happening here, but it&#x27;s a basic fact when writing benchmarks that you have to actually test something real and not a transient property of the program <i>after</i> the compiler has had its chance to be really smart.
barbarbaralmost 6 years ago
I am a bit confused. The scanFile reads from a file. But the readLines inside the for loop is reading from a StringReader - and not from a file?
chvidalmost 6 years ago
At least two problems with the java code. Concatenation of strings using the plus operator creates a new string and copies the content of the old, that pushes the complexity of the code from o(n) to o(n2) where n is the number of lines. Secondly order is not guaranteed with the for each operation on streams.<p>The correct way to do it is using collect(Collectors.joining(“\n”)) or straight forward imperative style (without streams).<p>I don’t think the general statement holds (that java or buffered reader is cpu bound in particular).
评论 #20543645 未加载
IloveHN84almost 6 years ago
But all the stream API isso terribile for performance..you write a one line code and you are already at O(n^5)
pjmlpalmost 6 years ago
Completely wrong.<p>It is like asserting something about C based on GCC specific behaviour.<p>Java is not a single language implementation.
评论 #20543781 未加载
nottorpalmost 6 years ago
Java is... java.<p>I was once working on an Android app on a cheap custom board with 128 M ram (don&#x27;t ask why Android on a single function custom board, wasn&#x27;t my decision).<p>Among other things, I had to parse a 80000 line csv file. Splitting and the rest of the processing created so many temporary strings the system ran out of ram. We eventually gave up.
评论 #20542309 未加载
评论 #20542414 未加载
评论 #20548034 未加载
评论 #20542800 未加载
评论 #20543315 未加载
评论 #20542267 未加载
评论 #20542315 未加载