Skip to content

Commit 976ece0

Browse files
committed
getenvW: Reduce the amount of parsing done on unmatchable keys
Instead of parsing the full key and value for each environment variable before checking the key for (case-insensitive) equality, we skip to the next environment variable once it's no longer possible for the key to match. This makes getting environment variables about 2x faster across the board on Windows. Note: We still have to scan to find the end of each environment variable, even the ones that are skipped (we only know where it ends by a NUL terminator), so this strategy doesn't provide the same speedup on Windows as it does on POSIX (#23265)
1 parent 974e9c8 commit 976ece0

File tree

1 file changed

+11
-14
lines changed

1 file changed

+11
-14
lines changed

lib/std/process.zig

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -529,29 +529,26 @@ pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
529529
const key_slice = mem.sliceTo(key, 0);
530530
const ptr = windows.peb().ProcessParameters.Environment;
531531
var i: usize = 0;
532-
while (ptr[i] != 0) {
532+
while (ptr[i] != 0) : (i += mem.sliceTo(ptr[i..], 0).len + 1) {
533533
const key_start = i;
534534

535535
// There are some special environment variables that start with =,
536536
// so we need a special case to not treat = as a key/value separator
537537
// if it's the first character.
538538
// 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];
539+
if (ptr[key_start] == '=') {
540+
if (key[0] != '=') continue;
541+
i += 1;
542+
}
549543

550-
if (windows.eqlIgnoreCaseWTF16(key_slice, this_key)) {
551-
return this_value;
544+
const upcaseW = windows.ntdll.RtlUpcaseUnicodeChar;
545+
while (ptr[i] != 0 and key[i - key_start] != 0) : (i += 1) {
546+
if (i - key_start == key_slice.len) break;
547+
if (upcaseW(ptr[i]) != upcaseW(key[i - key_start])) break;
552548
}
549+
if ((i - key_start != key_slice.len) or (ptr[i] != '=')) continue;
553550

554-
i += 1; // skip over null byte
551+
return mem.sliceTo(ptr[i + 1 ..], 0);
555552
}
556553
return null;
557554
}

0 commit comments

Comments
 (0)