Skip to content

Commit

Permalink
Update Spicy runtime driver to use new stream features for improved p…
Browse files Browse the repository at this point in the history
…erformance.

This does two things:

- When adding data to a stream, we now do that without copying
  anything initially. For block input (e.g., UDP) that's always fine
  because the parser will never suspend before it's fully done
  parsing; hence we can safely delete it once the parser returns. For
  stream input (e.g., TCP), we make the stream own its data later
  if (and only if) the parser suspends.

- For block input (e.g., UDP) we now keep reusing the same stream for
  subsequent blocks, instead of creating a new one each time. This
  allows the stream to reuse an allocated chunk that it may have still
  cached internally.

The result of this, plus the new chunk caching introduced earlier, is
that for a UDP flow, we never need to allocate more than one chunk,
and never need to copy any data; and for TCP it's the same as long as
parsing consumes all data before suspending (which should be a common
case), plus, when we allocate new storage we only copy data that didn't
get trimmed immediately anyways.

Closes #1657.
  • Loading branch information
rsmmr committed Apr 19, 2024
1 parent 347d7fe commit a455ce7
Showing 1 changed file with 19 additions and 11 deletions.
30 changes: 19 additions & 11 deletions spicy/runtime/src/driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,21 @@ driver::ParsingState::State driver::ParsingState::_process(size_t size, const ch
assert(_parser->profiler_tags);
auto profiler = hilti::rt::profiler::start(_parser->profiler_tags.prepare_block);

auto input = hilti::rt::reference::make_value<hilti::rt::Stream>(data, size);
input->freeze();
if ( ! _input ) {
_input =
hilti::rt::reference::make_value<hilti::rt::Stream>(data, size, hilti::rt::stream::NonOwning());

if ( ! _parser->parse1 )
throw InvalidUnitType(
fmt("unit type '%s' cannot be used as external entry point because it requires arguments",
_parser->name));
}
else {
(*_input)->reset();
(*_input)->append(data, size, hilti::rt::stream::NonOwning());
}

if ( ! _parser->parse1 )
throw InvalidUnitType(
fmt("unit type '%s' cannot be used as external entry point because it requires arguments",
_parser->name));
(*_input)->freeze();

if ( _parser->context_new ) {
if ( _context )
Expand All @@ -273,9 +281,7 @@ driver::ParsingState::State driver::ParsingState::_process(size_t size, const ch

hilti::rt::profiler::stop(profiler);

_resumable = _parser->parse1(input, {}, _context);

if ( ! *_resumable )
if ( ! _parser->parse1(*_input, {}, _context) )
hilti::rt::internalError("block-based parsing yielded");

return Done;
Expand Down Expand Up @@ -305,7 +311,8 @@ driver::ParsingState::State driver::ParsingState::_process(size_t size, const ch
DRIVER_DEBUG("no context provided");
}

_input = hilti::rt::reference::make_value<hilti::rt::Stream>(data, size);
_input =
hilti::rt::reference::make_value<hilti::rt::Stream>(data, size, hilti::rt::stream::NonOwning());
if ( eod )
(*_input)->freeze();

Expand All @@ -323,7 +330,7 @@ driver::ParsingState::State driver::ParsingState::_process(size_t size, const ch
assert(_input && _resumable);

if ( size )
(*_input)->append(data, size);
(*_input)->append(data, size, hilti::rt::stream::NonOwning());

if ( eod ) {
DRIVER_DEBUG("end of data");
Expand All @@ -346,6 +353,7 @@ driver::ParsingState::State driver::ParsingState::_process(size_t size, const ch
if ( eod )
hilti::rt::internalError("parsing yielded for final data chunk");

(*_input)->makeOwning();
return Continue;
}
}
Expand Down

0 comments on commit a455ce7

Please sign in to comment.