Optimise Derivation::unparse()

In

  nix-instantiate --dry-run '<nixpkgs/nixos/release-combined.nix>' -A nixos.tests.simple.x86_64-linux

this reduces time spent in unparse() from 9.15% to 4.31%. The main
culprit was appending characters one at a time to the destination
string. Even though the string has enough capacity, push_back() still
needs to check this on every call.
This commit is contained in:
Eelco Dolstra 2020-02-23 16:36:19 +01:00
parent 401b5bc541
commit 75db069f92
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -213,15 +213,26 @@ Derivation Store::derivationFromPath(const StorePath & drvPath)
} }
static void printString(string & res, const string & s) static void printString(string & res, std::string_view s)
{
char buf[s.size() * 2 + 2];
char * p = buf;
*p++ = '"';
for (auto c : s)
if (c == '\"' || c == '\\') { *p++ = '\\'; *p++ = c; }
else if (c == '\n') { *p++ = '\\'; *p++ = 'n'; }
else if (c == '\r') { *p++ = '\\'; *p++ = 'r'; }
else if (c == '\t') { *p++ = '\\'; *p++ = 't'; }
else *p++ = c;
*p++ = '"';
res.append(buf, p - buf);
}
static void printUnquotedString(string & res, std::string_view s)
{ {
res += '"'; res += '"';
for (const char * i = s.c_str(); *i; i++) res.append(s);
if (*i == '\"' || *i == '\\') { res += "\\"; res += *i; }
else if (*i == '\n') res += "\\n";
else if (*i == '\r') res += "\\r";
else if (*i == '\t') res += "\\t";
else res += *i;
res += '"'; res += '"';
} }
@ -239,6 +250,19 @@ static void printStrings(string & res, ForwardIterator i, ForwardIterator j)
} }
template<class ForwardIterator>
static void printUnquotedStrings(string & res, ForwardIterator i, ForwardIterator j)
{
res += '[';
bool first = true;
for ( ; i != j; ++i) {
if (first) first = false; else res += ',';
printUnquotedString(res, *i);
}
res += ']';
}
string Derivation::unparse(const Store & store, bool maskOutputs, string Derivation::unparse(const Store & store, bool maskOutputs,
std::map<std::string, StringSet> * actualInputs) const std::map<std::string, StringSet> * actualInputs) const
{ {
@ -249,10 +273,10 @@ string Derivation::unparse(const Store & store, bool maskOutputs,
bool first = true; bool first = true;
for (auto & i : outputs) { for (auto & i : outputs) {
if (first) first = false; else s += ','; if (first) first = false; else s += ',';
s += '('; printString(s, i.first); s += '('; printUnquotedString(s, i.first);
s += ','; printString(s, maskOutputs ? "" : store.printStorePath(i.second.path)); s += ','; printUnquotedString(s, maskOutputs ? "" : store.printStorePath(i.second.path));
s += ','; printString(s, i.second.hashAlgo); s += ','; printUnquotedString(s, i.second.hashAlgo);
s += ','; printString(s, i.second.hash); s += ','; printUnquotedString(s, i.second.hash);
s += ')'; s += ')';
} }
@ -261,24 +285,24 @@ string Derivation::unparse(const Store & store, bool maskOutputs,
if (actualInputs) { if (actualInputs) {
for (auto & i : *actualInputs) { for (auto & i : *actualInputs) {
if (first) first = false; else s += ','; if (first) first = false; else s += ',';
s += '('; printString(s, i.first); s += '('; printUnquotedString(s, i.first);
s += ','; printStrings(s, i.second.begin(), i.second.end()); s += ','; printUnquotedStrings(s, i.second.begin(), i.second.end());
s += ')'; s += ')';
} }
} else { } else {
for (auto & i : inputDrvs) { for (auto & i : inputDrvs) {
if (first) first = false; else s += ','; if (first) first = false; else s += ',';
s += '('; printString(s, store.printStorePath(i.first)); s += '('; printUnquotedString(s, store.printStorePath(i.first));
s += ','; printStrings(s, i.second.begin(), i.second.end()); s += ','; printUnquotedStrings(s, i.second.begin(), i.second.end());
s += ')'; s += ')';
} }
} }
s += "],"; s += "],";
auto paths = store.printStorePathSet(inputSrcs); // FIXME: slow auto paths = store.printStorePathSet(inputSrcs); // FIXME: slow
printStrings(s, paths.begin(), paths.end()); printUnquotedStrings(s, paths.begin(), paths.end());
s += ','; printString(s, platform); s += ','; printUnquotedString(s, platform);
s += ','; printString(s, builder); s += ','; printString(s, builder);
s += ','; printStrings(s, args.begin(), args.end()); s += ','; printStrings(s, args.begin(), args.end());