Skip to content

Commit f0b2eb7

Browse files
jockosdunglas
andauthored
feat: improve of performance of PHP variables registration (#94)
* feat: enhance php register variables * apply comments * fix errors * improve benchmark * remove debug statement * use defer * don't use defer in a loop Co-authored-by: Kévin Dunglas <kevin@dunglas.fr>
1 parent 3abda4f commit f0b2eb7

4 files changed

Lines changed: 48 additions & 8 deletions

File tree

frankenphp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,14 @@ static char* frankenphp_read_cookies(void)
474474
return ctx->cookie_data;
475475
}
476476

477+
void frankenphp_register_bulk_variables(char **variables, size_t size, zval *track_vars_array)
478+
{
479+
for (size_t i = 0; i < size; i++)
480+
{
481+
if (i%2 == 1) php_register_variable(variables[i-1], variables[i], track_vars_array);
482+
}
483+
}
484+
477485
static void frankenphp_register_variables(zval *track_vars_array)
478486
{
479487
/* https://www.php.net/manual/en/reserved.variables.server.php */

frankenphp.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,18 +444,25 @@ func go_register_variables(rh C.uintptr_t, trackVarsArray *C.zval) {
444444
r := cgo.Handle(rh).Value().(*http.Request)
445445
env = r.Context().Value(contextKey).(*FrankenPHPContext).Env
446446

447-
// FIXME: remove this debug statement
448-
env[fmt.Sprintf("REQUEST_%d", rh)] = "1"
447+
le := len(env) * 2
448+
cArr := (**C.char)(C.malloc(C.size_t(le) * C.size_t(unsafe.Sizeof((*C.char)(nil)))))
449+
defer C.free(unsafe.Pointer(cArr))
449450

450-
// TODO: batch this for performance
451+
variables := unsafe.Slice(cArr, le)
452+
453+
var i int
451454
for k, v := range env {
452-
ck := C.CString(k)
453-
cv := C.CString(v)
455+
variables[i] = C.CString(k)
456+
i++
457+
458+
variables[i] = C.CString(v)
459+
i++
460+
}
454461

455-
C.php_register_variable(ck, cv, trackVarsArray)
462+
C.frankenphp_register_bulk_variables(cArr, C.size_t(le), trackVarsArray)
456463

457-
C.free(unsafe.Pointer(ck))
458-
C.free(unsafe.Pointer(cv))
464+
for _, v := range variables {
465+
C.free(unsafe.Pointer(v))
459466
}
460467
}
461468

frankenphp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define _FRANKENPPHP_H
33

44
#include <stdint.h>
5+
#include <Zend/zend_types.h>
56

67
int frankenphp_check_version();
78
int frankenphp_init(int num_threads);
@@ -26,5 +27,6 @@ uintptr_t frankenphp_clean_server_context();
2627
int frankenphp_request_startup();
2728
int frankenphp_execute_script(const char *file_name);
2829
uintptr_t frankenphp_request_shutdown();
30+
void frankenphp_register_bulk_variables(char **variables, size_t size, zval *track_vars_array);
2931

3032
#endif

frankenphp_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,29 @@ func runTest(t *testing.T, test func(func(http.ResponseWriter, *http.Request), *
8888
wg.Wait()
8989
}
9090

91+
func BenchmarkHelloWorld(b *testing.B) {
92+
if err := frankenphp.Init(frankenphp.WithLogger(zap.NewNop())); err != nil {
93+
panic(err)
94+
}
95+
defer frankenphp.Shutdown()
96+
cwd, _ := os.Getwd()
97+
testDataDir := cwd + "/testdata/"
98+
99+
handler := func(w http.ResponseWriter, r *http.Request) {
100+
req := frankenphp.NewRequestWithContext(r, testDataDir, nil)
101+
if err := frankenphp.ServeHTTP(w, req); err != nil {
102+
panic(err)
103+
}
104+
}
105+
106+
req := httptest.NewRequest("GET", "http://example.com/index.php", nil)
107+
w := httptest.NewRecorder()
108+
109+
for i := 0; i < b.N; i++ {
110+
handler(w, req)
111+
}
112+
}
113+
91114
func TestHelloWorld_module(t *testing.T) { testHelloWorld(t, nil) }
92115
func TestHelloWorld_worker(t *testing.T) { testHelloWorld(t, &testOptions{workerScript: "index.php"}) }
93116
func testHelloWorld(t *testing.T, opts *testOptions) {

0 commit comments

Comments
 (0)