From bf31d3f9a9e1d4eb14831e2b38941826e925964f Mon Sep 17 00:00:00 2001 From: Markus Triska Date: Thu, 17 Apr 2025 22:14:37 +0200 Subject: [PATCH] ENHANCED: dedicated faster branches for repositionable streams rebis-dev makes the speed difference especially apparent due to the linear scan of strings on the heap in partial_string_tail/2 which is now avoided for repositionable streams, notably files. This addresses #2888 reported and analyzed by @haijinSk. Many thanks! --- src/lib/pio.pl | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/lib/pio.pl b/src/lib/pio.pl index f13c9b85..0204a19e 100644 --- a/src/lib/pio.pl +++ b/src/lib/pio.pl @@ -39,7 +39,8 @@ % represented as a list of characters. phrase_from_stream(GRBody, Stream) :- - stream_to_lazy_list(Stream, Ls), + stream_property(Stream, reposition(Reposition)), + stream_to_lazy_list(Reposition, Stream, Ls), phrase(GRBody, Ls). %% phrase_from_file(+GRBody, +File) @@ -64,7 +65,7 @@ phrase_from_file(NT, File, Options) :- ; Type = text ), setup_call_cleanup( - open(File, read, Stream, Options), + open(File, read, Stream, [reposition(true)|Options]), phrase_from_stream(NT, Stream), close(Stream) ) @@ -73,34 +74,41 @@ phrase_from_file(NT, File, Options) :- % How many chars to read from stream and buffer in each step chars_to_read(4096). -stream_to_lazy_list(Stream, Ls) :- - get_stream_buffer_position(Stream, Pos), - freeze(Ls, render_step(Stream, Pos, Ls)). +stream_to_lazy_list(Reposition, Stream, Ls) :- + get_stream_buffer_position(Reposition, Stream, Pos), + freeze(Ls, render_step(Reposition, Stream, Pos, Ls)). -render_step(Stream, Pos, Ls) :- - set_stream_buffer_position(Stream, Pos), - ( buffer_at_end_of_stream(Stream) -> +render_step(Reposition, Stream, Pos, Ls) :- + set_stream_buffer_position(Reposition, Stream, Pos), + ( buffer_at_end_of_stream(Reposition, Stream) -> Ls = [] ; chars_to_read(CharsToRead), - buffer_get_n_chars(Stream, CharsToRead, Chars), + buffer_get_n_chars(Reposition, Stream, CharsToRead, Chars), partial_string(Chars, Ls, Ls0), - stream_to_lazy_list(Stream, Ls0) + stream_to_lazy_list(Reposition, Stream, Ls0) ). -buffer_at_end_of_stream(Stream) :- +buffer_at_end_of_stream(true, Stream) :- at_end_of_stream(Stream). +buffer_at_end_of_stream(false, Stream) :- stream_bufferids(Stream, _, BufferPosId, _), bb_get(BufferPosId, Pos), Pos = eof. -get_stream_buffer_position(Stream, Pos) :- +get_stream_buffer_position(true, Stream, Pos) :- + stream_property(Stream, position(Pos)). +get_stream_buffer_position(false, Stream, Pos) :- stream_bufferids(Stream, _, BufferPosId, _), bb_get(BufferPosId, Pos). -set_stream_buffer_position(Stream, Pos) :- +set_stream_buffer_position(true, Stream, Pos) :- + set_stream_position(Stream, Pos). +set_stream_buffer_position(false, Stream, Pos) :- stream_bufferids(Stream, _, BufferPosId, _), bb_put(BufferPosId, Pos). -buffer_get_n_chars(Stream, N, Chars) :- +buffer_get_n_chars(true, Stream, N, Chars) :- + get_n_chars(Stream, N, Chars). +buffer_get_n_chars(false, Stream, N, Chars) :- stream_bufferids(Stream, BufferId, BufferPosId, BufferLenId), buffer_prepare_for_n(Stream, BufferId, BufferPosId, BufferLenId, N), bb_get(BufferId, Buffer), -- 2.54.0