1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 20:16:03 +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());
}
// 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
BENCHMARK_CAPTURE(
BM_ParseRealDerivationFile,
@ -37,3 +58,11 @@ BENCHMARK_CAPTURE(
BM_ParseRealDerivationFile,
firefox,
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,12 +498,16 @@ Derivation parseDerivation(
*/
static void printString(std::string & res, std::string_view s)
{
boost::container::small_vector<char, 64 * 1024> buffer;
buffer.reserve(s.size() * 2 + 2);
res.reserve(res.size() + s.size() * 2 + 2);
res += '"';
static constexpr auto chunkSize = 1024;
std::array<char, 2 * chunkSize + 2> buffer;
while (!s.empty()) {
auto chunk = s.substr(0, /*n=*/chunkSize);
s.remove_prefix(chunk.size());
char * buf = buffer.data();
char * p = buf;
*p++ = '"';
for (auto c : s)
for (auto c : chunk)
if (c == '\"' || c == '\\') {
*p++ = '\\';
*p++ = c;
@ -518,8 +522,9 @@ static void printString(std::string & res, std::string_view s)
*p++ = 't';
} else
*p++ = c;
*p++ = '"';
res.append(buf, p - buf);
}
res += '"';
}
static void printUnquotedString(std::string & res, std::string_view s)