Frank-en-stein opened a new issue, #13735:
URL: https://github.com/apache/maven/issues/13735

   ### Affected version
   
   3.10.0 (JLine 3.30.17 / jansi-core 3.30.17). Not affected: 3.9.16 and 
earlier.
   
   ### Bug description
   
   ## What happens
   
   When stdout is a pipe or a file, Maven 3.10.0 issues one write(2) syscall 
per byte of console output.
   Maven 3.9.x wrote the same output in 8 KiB chunks.
   
   This matters in CI. Tools that read the pipe (buildkit, Earthly, Jenkins, 
Docker) receive thousands
   of tiny chunks per line. In our case a 15 KB surefire log line became 
thousands of log fragments,
   the CI log pipeline saturated, and the forked test JVM blocked on stdout. A 
4 minute `mvn test`
   job no longer finished within 45 minutes.
   
   ## Impact
   
   We run `mvn --batch-mode --quiet test` under Earthly/buildkit in the 
`maven:3.10.0-amazoncorretto-21-alpine` image. The tests log JSON lines, some 
with 15 KB stack traces.
   
   - Job time went from 4 minutes on 3.9.9 to cancelled at 45 minutes on 
3.10.0, on every run that rebuilt the test layer. Four branches were blocked in 
one afternoon.
   - Output reached the CI runner 30 minutes late, in 3 to 4 byte fragments, at 
20 to 40 seconds per 15 KB line. The job log grew to 2.5 GB.
   - Once the pipes filled, the test JVM blocked inside its logging appender 
and looked hung.
   
   No Maven option restored the old behaviour. We have pinned our shared build 
image to 3.9.16 and cannot move to the 3.10 line until this is fixed.
   
   ## Cause
   
   `MessageUtils.systemInstall()` builds a dumb terminal and calls 
`AnsiConsole.systemInstall()`.
   That wraps `terminal.output()`, an unbuffered `FileOutputStream`, in 
`org.jline.jansi.io.AnsiOutputStream`.
   `AnsiOutputStream` extends `FilterOutputStream` and only overrides 
`write(int)`, so `write(byte[], int, int)`
   falls back to one `write(int)` per byte, and each one reaches the kernel.
   
   Jansi 2.x (used by 3.9.x) wrapped the descriptor in 
`FastBufferedOutputStream` first, so the bytes were coalesced.
   
   ## Reproduce
   
   1. Any project with maven-surefire-plugin 3.6.1 and a JUnit test that prints 
a few 15 KB lines to System.out.
   2. `strace -f -e trace=write -o trace.txt mvn -B -q test | cat > /dev/null`
   3. Count writes to fd 1 in trace.txt.
   
   Results (same project, same JDK 21):
   
   | Maven  | writes to stdout | single-byte writes |
   | ------ | ---------------: | -----------------: |
   | 3.9.16 |               30 |                  6 |
   | 3.10.0 |           88,524 |             88,506 |
   
   `-Dstyle.color=never`, `-Djansi.mode=strip`, `-Djansi.mode=force`, 
`-Djansi.providers=none` and
   `-Dorg.jline.terminal.dumb=true` make no difference. Only `-l /dev/stdout` 
avoids it, because that
   replaces System.out with a plain PrintStream.
   
   ## Expected
   
   Console output should reach the kernel in buffered chunks regardless of 
whether stdout is a terminal.
   Either `AnsiOutputStream` should implement `write(byte[], int, int)`, or 
Maven should wrap the dumb
   terminal's output in a `BufferedOutputStream` before installing it (and 
flush on each log event).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to