RFR: 8358533: Improve performance of java.io.Reader.readAllLines [v8]

Xueming Shen sherman at openjdk.org
Sat Jun 28 08:44:40 UTC 2025


On Fri, 27 Jun 2025 19:41:01 GMT, Brian Burkhalter <bpb at openjdk.org> wrote:

>> Replaces the implementation `readAllCharsAsString().lines().toList()` with reading into a temporary `char` array which is then processed to detect line terminators and copy non-terminating characters into strings which are added to the list.
>
> Brian Burkhalter has updated the pull request incrementally with one additional commit since the last revision:
> 
>   8358533: Make no line terminator case clearer

It seems the only additional info needed to handle resizing and line fragment preservation is the start position of the current line. We might be able to consolidate the two nested parsing loops into a single loop as well, which should improve/speed up the iteration performance. The PoC reference code below seems to work as expected, though not fully tested :-)

    public List<String> readAllLines() throws IOException {
        List<String> lines = new ArrayList<>();
        char[] cb = new char[TRANSFER_BUFFER_SIZE];

        int start = 0;
        int pos = 0;
        int limit = 0;
        boolean skipLF = false;
        int n;
        while ((n = read(cb, pos, cb.length - pos)) != -1) {
            limit = pos + n;
            while (pos < limit) {
                if (skipLF ) {
                    if (cb[pos] == '\n') {
                        pos++;
                        start++;
                    }
                    skipLF = false;
                    if (pos == limit)
                        break;
                }
                char c = cb[pos++];
                if (c == '\n' || c == '\r') {
                    lines.add(new String(cb, start, pos - 1 - start));
                    skipLF =  (c == '\r');
                    start = pos;
                }
            }
            int len = limit - start;
            if (len >= cb.length) {
                // allocate larger buffer and copy chars to beginning
                char[] tmp = new char[2*cb.length];
                System.arraycopy(cb, start, tmp, 0, len);
                cb = tmp;
            } else if (start != 0 && len != 0) {
                // move fragment to beginning of buffer
                System.arraycopy(cb, start, cb, 0, len);
            }
            pos = limit = len;
            start = 0;
        }
        // add a string if EOS terminates the last line
        if (limit > start)
            lines.add(new String(cb, start, limit - start));

        return Collections.unmodifiableList(lines);
    }

-------------

PR Comment: https://git.openjdk.org/jdk/pull/25863#issuecomment-3015110296


More information about the core-libs-dev mailing list