Skip to content

Commit a00bb02

Browse files
authored
perf: small native tls optimisation (#2512)
This folds a 3 instruction tls load on aarch64 to a single mrs. On x86-64 gnu ld *should* have relaxed it to a single fs anyway, but this guarantees it. --------- Signed-off-by: Marc <m@pyc.ac>
1 parent 56ace59 commit a00bb02

5 files changed

Lines changed: 22 additions & 7 deletions

File tree

build-static.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ if [ -n "${COMPRESS}" ] && [ -z "${DEBUG_SYMBOLS}" ] && [ "${os}" = "linux" ]; t
195195
SPC_OPT_INSTALL_ARGS="${SPC_OPT_INSTALL_ARGS} upx"
196196
fi
197197

198+
MTLS_CFLAGS="$(sh "${CURRENT_DIR}/mtls-cflags.sh")"
199+
export CGO_CFLAGS="${CGO_CFLAGS} ${MTLS_CFLAGS}"
200+
198201
export SPC_DEFAULT_C_FLAGS="-fPIC -O2"
199202
if [ -n "${DEBUG_SYMBOLS}" ]; then
200203
SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS="${SPC_CMD_VAR_PHP_MAKE_EXTRA_CFLAGS} -fPIE -g"

docs/performance.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ We strongly recommend changing these values. For best system stability, it is re
1818
To find the right values, it's best to run load tests simulating real traffic.
1919
[k6](https://k6.io) and [Gatling](https://gatling.io) are good tools for this.
2020

21-
To configure the number of threads, use the `num_threads` option of the `php_server` and `php` directives.
21+
To configure the number of threads, use the `num_threads` option of the global `frankenphp` directive.
2222
To change the number of workers, use the `num` option of the `worker` section of the `frankenphp` directive.
2323

2424
### `max_threads`

frankenphp.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,27 @@ bool original_user_abort_setting = 0;
9898
frankenphp_interned_strings_t frankenphp_strings = {0};
9999
HashTable *main_thread_env = NULL;
100100

101-
__thread uintptr_t thread_index;
102-
__thread bool is_worker_thread = false;
103-
__thread HashTable *sandboxed_env = NULL;
101+
#if defined(__ELF__) && defined(__GNUC__)
102+
#define THREAD_LOCAL __thread __attribute__((tls_model("local-exec")))
103+
#else
104+
#define THREAD_LOCAL __thread
105+
#endif
106+
107+
static THREAD_LOCAL uintptr_t thread_index;
108+
static THREAD_LOCAL bool is_worker_thread = false;
109+
static THREAD_LOCAL HashTable *sandboxed_env = NULL;
104110
/* prepared_env holds entries from php(_server)'s `env KEY VAL`, exposed to
105111
* getenv() and merged into $_ENV when 'E' is in variables_order. Separate from
106112
* putenv() so those don't leak into $_ENV. */
107-
__thread HashTable *prepared_env = NULL;
113+
static THREAD_LOCAL HashTable *prepared_env = NULL;
108114

109115
/* Published via SG(server_context) so ext-parallel children, which inherit
110116
* the parent's SG(server_context), can route SAPI callbacks back to the
111117
* parent's thread_index instead of their zero-initialized TLS. */
112118
typedef struct {
113119
uintptr_t thread_index;
114120
} frankenphp_server_ctx;
115-
static __thread frankenphp_server_ctx frankenphp_local_server_ctx;
121+
static THREAD_LOCAL frankenphp_server_ctx frankenphp_local_server_ctx;
116122

117123
static inline uintptr_t frankenphp_thread_index(void) {
118124
frankenphp_server_ctx *ctx = (frankenphp_server_ctx *)SG(server_context);

go.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
# Runs the go command with the proper Go and cgo flags.
33

44
GOFLAGS="$GOFLAGS -tags=nobadger,nomysql,nopgx" \
5-
CGO_CFLAGS="$CGO_CFLAGS $(php-config --includes)" \
5+
CGO_CFLAGS="$CGO_CFLAGS $(php-config --includes) $(sh "$(dirname "$0")/mtls-cflags.sh")" \
66
CGO_LDFLAGS="$CGO_LDFLAGS $(php-config --ldflags) $(php-config --libs)" \
77
go "$@"

mtls-cflags.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
# Prints -mtls-size=12 if the toolchain compiles and links local-exec TLS with it (excludes non-AArch64 and ld.lld).
3+
d="$(mktemp -d)" || exit 0
4+
printf '__thread __attribute__((tls_model("local-exec"))) int v;\nint main(void){v=1;return v;}\n' >"$d/p.c"
5+
"${CC:-cc}" -O2 -mtls-size=12 "$d/p.c" -o "$d/p" >/dev/null 2>&1 && printf -- -mtls-size=12
6+
rm -rf "$d"

0 commit comments

Comments
 (0)