Skip to content

Commit

Permalink
Reduce string allocations on hot parse path.
Browse files Browse the repository at this point in the history
When waiting for input we pass down strings for a possible error message
and the triggering location. In generated code these are always
literals.

With this patch we do not take them as owning strings, but instead as
views into existing strings to minimize allocations. In the case of
error messages the created low-level exception objects already had used
string_views, so this also aligns the APIs.

Closes #1589.
  • Loading branch information
bbannier committed Nov 17, 2023
1 parent cf2cb8c commit 842a3df
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 9 deletions.
11 changes: 6 additions & 5 deletions spicy/runtime/include/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <algorithm>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
Expand Down Expand Up @@ -316,7 +317,7 @@ inline auto parsers() {
*/
class ParseError : public hilti::rt::RecoverableFailure {
public:
ParseError(const std::string& msg, const std::string& location = "") : RecoverableFailure(msg, location) {}
ParseError(std::string_view msg, std::string_view location = "") : RecoverableFailure(msg, location) {}

ParseError(const hilti::rt::result::Error& e) : RecoverableFailure(e.description()) {}

Expand All @@ -336,7 +337,7 @@ class Backtrack : public ParseError {

class MissingData : public ParseError {
public:
MissingData(const std::string& location = "") : ParseError("missing data", location) {}
MissingData(std::string_view location = "") : ParseError("missing data", location) {}
~MissingData() override; /* required to create vtable, see hilti::rt::Exception */
};

Expand Down Expand Up @@ -452,8 +453,8 @@ extern void waitForEod(hilti::rt::ValueReference<hilti::rt::Stream>& data, // NO
* has been reached
*/
extern void waitForInput(hilti::rt::ValueReference<hilti::rt::Stream>& data, // NOLINT(google-runtime-references)
const hilti::rt::stream::View& cur, uint64_t min, const std::string& error_msg,
const std::string& location,
const hilti::rt::stream::View& cur, uint64_t min, std::string_view error_msg,
std::string_view location,
hilti::rt::StrongReference<spicy::rt::filter::detail::Filters> filters);

/**
Expand Down Expand Up @@ -484,7 +485,7 @@ extern bool waitForInputOrEod(hilti::rt::ValueReference<hilti::rt::Stream>& data
* has been reached
*/
extern void waitForInput(hilti::rt::ValueReference<hilti::rt::Stream>& data, // NOLINT(google-runtime-references)
const hilti::rt::stream::View& cur, const std::string& error_msg, const std::string& location,
const hilti::rt::stream::View& cur, std::string_view error_msg, std::string_view location,
const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters);

/**
Expand Down
8 changes: 4 additions & 4 deletions spicy/runtime/src/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,14 @@ void detail::waitForEod(hilti::rt::ValueReference<hilti::rt::Stream>& data, cons
}

void detail::waitForInput(hilti::rt::ValueReference<hilti::rt::Stream>& data, const hilti::rt::stream::View& cur,
uint64_t min, const std::string& error_msg, const std::string& location,
uint64_t min, std::string_view error_msg, std::string_view location,
hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>
filters) { // NOLINT(performance-unnecessary-value-param)
while ( min > cur.size() )
if ( ! waitForInputOrEod(data, cur, filters) ) {
SPICY_RT_DEBUG_VERBOSE(
hilti::rt::fmt("insufficient input at end of data for stream %p (which is not ok here)", data.get()));
throw ParseError(error_msg, location);
throw ParseError(std::string(error_msg), std::string(location));
}
}

Expand Down Expand Up @@ -156,12 +156,12 @@ bool detail::waitForInputOrEod(hilti::rt::ValueReference<hilti::rt::Stream>& dat
}

void detail::waitForInput(hilti::rt::ValueReference<hilti::rt::Stream>& data, const hilti::rt::stream::View& cur,
const std::string& error_msg, const std::string& location,
std::string_view error_msg, std::string_view location,
const hilti::rt::StrongReference<spicy::rt::filter::detail::Filters>& filters) {
if ( ! waitForInputOrEod(data, cur, filters) ) {
SPICY_RT_DEBUG_VERBOSE(
hilti::rt::fmt("insufficient input at end of data for stream %p (which is not ok here)", data.get()));
throw ParseError(error_msg, location);
throw ParseError(std::string(error_msg), std::string(location));
}
}

Expand Down

0 comments on commit 842a3df

Please sign in to comment.