1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 12:06:01 +01:00

Merge pull request #13877 from xokdvium/opt-print-string

libstore: Get rid of allocations in printString, allocate 2K bytes on the stack
This commit is contained in:
John Ericson 2025-08-31 00:42:18 -04:00 committed by GitHub
commit 2746985d90
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 56 additions and 22 deletions

View file

@ -28,6 +28,27 @@ static void BM_ParseRealDerivationFile(benchmark::State & state, const std::stri
state.SetBytesProcessed(state.iterations() * content.size()); state.SetBytesProcessed(state.iterations() * content.size());
} }
// Benchmark unparsing real derivation files
static void BM_UnparseRealDerivationFile(benchmark::State & state, const std::string & filename)
{
// Read the file once
std::ifstream file(filename);
std::stringstream buffer;
buffer << file.rdbuf();
std::string content = buffer.str();
auto store = openStore("dummy://");
ExperimentalFeatureSettings xpSettings;
auto drv = parseDerivation(*store, std::string(content), "test", xpSettings);
for (auto _ : state) {
auto unparsed = drv.unparse(*store, /*maskOutputs=*/false);
benchmark::DoNotOptimize(unparsed);
assert(unparsed.size() == content.size());
}
state.SetBytesProcessed(state.iterations() * content.size());
}
// Register benchmarks for actual test derivation files if they exist // Register benchmarks for actual test derivation files if they exist
BENCHMARK_CAPTURE( BENCHMARK_CAPTURE(
BM_ParseRealDerivationFile, BM_ParseRealDerivationFile,
@ -37,3 +58,11 @@ BENCHMARK_CAPTURE(
BM_ParseRealDerivationFile, BM_ParseRealDerivationFile,
firefox, firefox,
getEnvNonEmpty("_NIX_TEST_UNIT_DATA").value_or(NIX_UNIT_TEST_DATA) + "/derivation/firefox.drv"); getEnvNonEmpty("_NIX_TEST_UNIT_DATA").value_or(NIX_UNIT_TEST_DATA) + "/derivation/firefox.drv");
BENCHMARK_CAPTURE(
BM_UnparseRealDerivationFile,
hello,
getEnvNonEmpty("_NIX_TEST_UNIT_DATA").value_or(NIX_UNIT_TEST_DATA) + "/derivation/hello.drv");
BENCHMARK_CAPTURE(
BM_UnparseRealDerivationFile,
firefox,
getEnvNonEmpty("_NIX_TEST_UNIT_DATA").value_or(NIX_UNIT_TEST_DATA) + "/derivation/firefox.drv");

View file

@ -498,28 +498,33 @@ Derivation parseDerivation(
*/ */
static void printString(std::string & res, std::string_view s) static void printString(std::string & res, std::string_view s)
{ {
boost::container::small_vector<char, 64 * 1024> buffer; res.reserve(res.size() + s.size() * 2 + 2);
buffer.reserve(s.size() * 2 + 2); res += '"';
char * buf = buffer.data(); static constexpr auto chunkSize = 1024;
char * p = buf; std::array<char, 2 * chunkSize + 2> buffer;
*p++ = '"'; while (!s.empty()) {
for (auto c : s) auto chunk = s.substr(0, /*n=*/chunkSize);
if (c == '\"' || c == '\\') { s.remove_prefix(chunk.size());
*p++ = '\\'; char * buf = buffer.data();
*p++ = c; char * p = buf;
} else if (c == '\n') { for (auto c : chunk)
*p++ = '\\'; if (c == '\"' || c == '\\') {
*p++ = 'n'; *p++ = '\\';
} else if (c == '\r') { *p++ = c;
*p++ = '\\'; } else if (c == '\n') {
*p++ = 'r'; *p++ = '\\';
} else if (c == '\t') { *p++ = 'n';
*p++ = '\\'; } else if (c == '\r') {
*p++ = 't'; *p++ = '\\';
} else *p++ = 'r';
*p++ = c; } else if (c == '\t') {
*p++ = '"'; *p++ = '\\';
res.append(buf, p - buf); *p++ = 't';
} else
*p++ = c;
res.append(buf, p - buf);
}
res += '"';
} }
static void printUnquotedString(std::string & res, std::string_view s) static void printUnquotedString(std::string & res, std::string_view s)