@@ -787,6 +787,21 @@ void tsvFilter(in TsvFilterOptions cmdopt, in string[] inputFiles)
787787 import std.range ;
788788 import tsvutil : throwIfWindowsNewlineOnUnix;
789789
790+ /* An output buffer. Improves performance on narrow files with high percentages of
791+ * writes. Want responsive output if output is rare, so ensure the first matched
792+ * line is written, and that writes separated by long stretches of non-matched lines
793+ * are written.
794+ */
795+ enum bufferReserveSize = 11264 ;
796+ enum bufferFlushSize = 10240 ;
797+ enum maxInputLinesWithoutBufferFlush = 1024 ;
798+ size_t inputLinesWithoutBufferFlush = maxInputLinesWithoutBufferFlush + 1 ;
799+
800+ auto outputBuffer = appender! (char []);
801+ outputBuffer.reserve (bufferReserveSize);
802+
803+ scope (exit) if (outputBuffer.data.length > 0 ) write(outputBuffer.data);
804+
790805 /* Process each input file, one line at a time. */
791806 auto lineFields = new char [][](cmdopt.maxFieldIndex + 1 );
792807 bool headerWritten = false ;
@@ -801,7 +816,8 @@ void tsvFilter(in TsvFilterOptions cmdopt, in string[] inputFiles)
801816 /* Header. Output on the first file, skip subsequent files. */
802817 if (! headerWritten)
803818 {
804- writeln(line);
819+ outputBuffer.put(line);
820+ outputBuffer.put(' \n ' );
805821 headerWritten = true ;
806822 }
807823 }
@@ -840,11 +856,23 @@ void tsvFilter(in TsvFilterOptions cmdopt, in string[] inputFiles)
840856 */
841857 try
842858 {
859+ inputLinesWithoutBufferFlush++ ;
843860 bool passed = cmdopt.disjunct ?
844861 cmdopt.tests.any! (x => x(lineFields)) :
845862 cmdopt.tests.all! (x => x(lineFields));
846863 if (cmdopt.invert) passed = ! passed;
847- if (passed) writeln(line);
864+ if (passed)
865+ {
866+ outputBuffer.put(line);
867+ outputBuffer.put(' \n ' );
868+ if (outputBuffer.data.length >= bufferFlushSize ||
869+ inputLinesWithoutBufferFlush > maxInputLinesWithoutBufferFlush)
870+ {
871+ write(outputBuffer.data);
872+ outputBuffer.clear;
873+ inputLinesWithoutBufferFlush = 0 ;
874+ }
875+ }
848876 }
849877 catch (Exception exc)
850878 {
0 commit comments