Skip to content

Commit 66dcebc

Browse files
committed
getenvW: Take advantage of sliceTo/indexOfScalarPos optimizations
Both sliceTo and indexOfScalarPos use SIMD when available to speed up the search. On my x86_64 machine, this leads to getenvW being around 2-3x faster overall. Additionally, any future improvements to sliceTo/indexOfScalarPos will benefit getenvW.
1 parent 78ecf3b commit 66dcebc

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

Diff for: lib/std/process.zig

+15-13
Original file line numberDiff line numberDiff line change
@@ -527,31 +527,33 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
527527
@compileError("Windows-only");
528528
}
529529
const key_slice = mem.sliceTo(key, 0);
530+
// '=' anywhere but the start makes this an invalid environment variable name
531+
if (key_slice.len > 0 and std.mem.indexOfScalar(u16, key_slice[1..], '=') != null) {
532+
return null;
533+
}
530534
const ptr = windows.peb().ProcessParameters.Environment;
531535
var i: usize = 0;
532536
while (ptr[i] != 0) {
533-
const key_start = i;
537+
const key_value = mem.sliceTo(ptr[i..], 0);
534538

535539
// There are some special environment variables that start with =,
536540
// so we need a special case to not treat = as a key/value separator
537541
// if it's the first character.
538542
// https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
539-
if (ptr[key_start] == '=') i += 1;
540-
541-
while (ptr[i] != 0 and ptr[i] != '=') : (i += 1) {}
542-
const this_key = ptr[key_start..i];
543-
544-
if (ptr[i] == '=') i += 1;
545-
546-
const value_start = i;
547-
while (ptr[i] != 0) : (i += 1) {}
548-
const this_value = ptr[value_start..i :0];
543+
const equal_search_start: usize = if (key_value[0] == '=') 1 else 0;
544+
const equal_index = std.mem.indexOfScalarPos(u16, key_value, equal_search_start, '=') orelse {
545+
// This is enforced by CreateProcess.
546+
// If violated, CreateProcess will fail with INVALID_PARAMETER.
547+
unreachable; // must contain a =
548+
};
549549

550+
const this_key = key_value[0..equal_index];
550551
if (windows.eqlIgnoreCaseWTF16(key_slice, this_key)) {
551-
return this_value;
552+
return key_value[equal_index + 1 ..];
552553
}
553554

554-
i += 1; // skip over null byte
555+
// skip past the NUL terminator
556+
i += key_value.len + 1;
555557
}
556558
return null;
557559
}

0 commit comments

Comments
 (0)