forked from lix-project/lix
Fix performance of builtins.substring for empty substrings
When returning a 0-length substring, avoid calling coerceToString, since it returns a string_view with the string's length, which is expensive to compute for large strings.
This commit is contained in:
parent
84502674f8
commit
25c889baac
|
@ -3712,9 +3712,6 @@ static RegisterPrimOp primop_toString({
|
||||||
static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring");
|
int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring");
|
||||||
int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring");
|
|
||||||
NixStringContext context;
|
|
||||||
auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
|
|
||||||
|
|
||||||
if (start < 0)
|
if (start < 0)
|
||||||
state.debugThrowLastTrace(EvalError({
|
state.debugThrowLastTrace(EvalError({
|
||||||
|
@ -3722,6 +3719,22 @@ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
.errPos = state.positions[pos]
|
.errPos = state.positions[pos]
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
int len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring");
|
||||||
|
|
||||||
|
// Special-case on empty substring to avoid O(n) strlen
|
||||||
|
// This allows for the use of empty substrings to efficently capture string context
|
||||||
|
if (len == 0) {
|
||||||
|
state.forceValue(*args[2], pos);
|
||||||
|
if (args[2]->type() == nString) {
|
||||||
|
v.mkString("", args[2]->context());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NixStringContext context;
|
||||||
|
auto s = state.coerceToString(pos, *args[2], context, "while evaluating the third argument (the string) passed to builtins.substring");
|
||||||
|
|
||||||
v.mkString((unsigned int) start >= s->size() ? "" : s->substr(start, len), context);
|
v.mkString((unsigned int) start >= s->size() ? "" : s->substr(start, len), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue