Skip to content

perf: move sandboxed environment to the C side#2058

Open
AlliBalliBaba wants to merge 42 commits intomainfrom
refactor/cleanup-env
Open

perf: move sandboxed environment to the C side#2058
AlliBalliBaba wants to merge 42 commits intomainfrom
refactor/cleanup-env

Conversation

@AlliBalliBaba
Copy link
Contributor

This PR uses zend_array_dup to simplify the environment sandboxing logic. It removes the CGO overhead from $_ENV and $_SERVER registration in regular threads and saves some memory on many threads. (wip)

Quick Benchmark Main This PR
BenchmarkHelloWorld-20 7071 7482
BenchmarkEcho-20 12160 12098
BenchmarkServerSuperGlobal-20 5550 5829
BenchmarkUncommonHeaders-20 6444 6709

AlliBalliBaba and others added 30 commits November 1, 2025 21:33
* removes backoff.

* Adjusts comment.

* Suggestions by @dunglas

* Removes 'max_consecutive_failures'

* Removes 'max_consecutive_failures'

* Adjusts warning.

* Disables the logger in tests.

* Revert "Adjusts warning."

This reverts commit e93a6a9.

* Revert "Removes 'max_consecutive_failures'"

This reverts commit ba28ea0.

* Revert "Removes 'max_consecutive_failures'"

This reverts commit 32e649c.

* Only fails on max failures again.

* Restores failure timings.
# Conflicts:
#	phpmainthread_test.go
# Conflicts:
#	phpthread.go
#	threadworker.go
# Conflicts:
#	phpthread.go
#	threadinactive.go
#	threadregular.go
#	threadworker.go
#	worker.go
# Conflicts:
#	phpmainthread_test.go
#	threadregular.go
# Conflicts:
#	env.go
#	frankenphp.c
#	phpmainthread.go
#	phpthread.go
#	threadregular.go
# Conflicts:
#	env.go
#	frankenphp.c
#	phpmainthread.go
#	phpthread.go
#	threadregular.go
@AlliBalliBaba AlliBalliBaba marked this pull request as ready for review December 12, 2025 13:27
Comment on lines +317 to +330
// cut the string at the first '='
char *eq_pos = memchr(setting, '=', setting_len);
bool put_env_success = true;
if (eq_pos != NULL) {
size_t name_len = eq_pos - setting;
size_t value_len =
(setting_len > name_len + 1) ? (setting_len - name_len - 1) : 0;
put_env_success =
go_putenv(setting, (int)name_len, eq_pos + 1, (int)value_len);
if (put_env_success) {
zval val = {0};
ZVAL_STRINGL(&val, eq_pos + 1, value_len);
zend_hash_str_update(sandboxed_env, setting, name_len, &val);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important to note that doing string cutting like this is binary safe, in contrast to the php-src implementation (null bytes will be forwarded and rejected by go's putenv)

// verify putenv does not affect $_SERVER
$result = $_SERVER[$var] ?? null;
if ($result !== null) {
echo "MY_VAR is in \$_SERVER (not expected)\n";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we specifically need a check for $_SERVER?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aka shouldn't we also check for $_ENV?


// Inserting an invalid variable should fail (null byte in key)
putenv("INVALID\x0_VAR=value");
if (getenv("INVALID\x0_VAR")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also check the return value of putenv here to make sure it returns false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants