diff --git a/types.c b/types.c index 27cbdae2..2090546b 100644 --- a/types.c +++ b/types.c @@ -23,10 +23,10 @@ void __zend_hash_init__(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_array *__zend_new_array__(uint32_t size) { return zend_new_array(size); } bool is_internal_class(zend_class_entry *entry) { - return entry->create_object != NULL; + return entry->create_object != NULL; } -//serialize +// serialize zend_string *__zval_serialize__(zend_object *obj) { // find serialize in global function table and call it zval zv; @@ -36,9 +36,10 @@ zend_string *__zval_serialize__(zend_object *obj) { zval retval; zval params[1]; params[0] = zv; - if (call_user_function(EG(function_table), NULL, &func, &retval, 1, params) != SUCCESS) { - zval_ptr_dtor(&func); - return NULL; + if (call_user_function(EG(function_table), NULL, &func, &retval, 1, params) != + SUCCESS) { + zval_ptr_dtor(&func); + return NULL; } zval_ptr_dtor(&func); @@ -56,28 +57,28 @@ void __zval_unserialize__(zval *retval, zend_string *str) { zval params[1]; ZVAL_STR(¶ms[0], str); - if (call_user_function(EG(function_table), NULL, &func, retval, 1, params) != SUCCESS) { - ZVAL_NULL(retval); + if (call_user_function(EG(function_table), NULL, &func, retval, 1, params) != + SUCCESS) { + ZVAL_NULL(retval); } zval_ptr_dtor(&func); zend_string_release(str); } zend_object *__php_object_init__( - zval *zv, - const char *class_name, - size_t class_name_len, + zval *zv, const char *class_name, size_t class_name_len, zend_class_entry *ce // optional: pass NULL to look up by name ) { + if (!ce) { + zend_string *name = + zend_string_init_interned(class_name, class_name_len, 1); + ce = zend_lookup_class(name); if (!ce) { - zend_string *name = zend_string_init_interned(class_name, class_name_len, 1); - ce = zend_lookup_class(name); - if (!ce) { - return NULL; - } + return NULL; } + } - object_init_ex(zv, ce); + object_init_ex(zv, ce); - return Z_OBJ_P(zv); + return Z_OBJ_P(zv); } \ No newline at end of file diff --git a/types.go b/types.go index 00584391..57b28860 100644 --- a/types.go +++ b/types.go @@ -274,37 +274,47 @@ func PHPValue(value any) unsafe.Pointer { func phpValue(zval *C.zval, value any) { switch v := value.(type) { case nil: + // equvalent of: ZVAL_NULL *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_NULL case bool: + // equvalent of: ZVAL_BOOL if v { *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_TRUE } else { *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_FALSE } case int: + // equvalent of: ZVAL_LONG *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_LONG *(*C.zend_long)(unsafe.Pointer(&zval.value)) = C.zend_long(v) case int64: + // equvalent of: ZVAL_LONG *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_LONG *(*C.zend_long)(unsafe.Pointer(&zval.value)) = C.zend_long(v) case float64: + // equvalent of: ZVAL_DOUBLE *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_DOUBLE *(*C.double)(unsafe.Pointer(&zval.value)) = C.double(v) case string: if v == "" { + // equivalent: ZVAL_EMPTY_STRING *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_INTERNED_STRING_EX *(**C.zend_string)(unsafe.Pointer(&zval.value)) = C.zend_empty_string break } + // equvalent of: ZVAL_STRING *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_STRING_EX *(**C.zend_string)(unsafe.Pointer(&zval.value)) = phpString(v, false) case AssociativeArray: + // equvalent of: ZVAL_ARR *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX *(**C.zend_array)(unsafe.Pointer(&zval.value)) = phpArray(v.Map, v.Order) case map[string]any: + // equvalent of: ZVAL_ARR *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX *(**C.zend_array)(unsafe.Pointer(&zval.value)) = phpArray(v, nil) case []any: + // equvalent of: ZVAL_ARR *(*uint32)(unsafe.Pointer(&zval.u1)) = C.IS_ARRAY_EX *(**C.zend_array)(unsafe.Pointer(&zval.value)) = (*C.zend_array)(PHPPackedArray(v)) case Object: diff --git a/types.h b/types.h index e994fa17..af7e6aa3 100644 --- a/types.h +++ b/types.h @@ -18,11 +18,7 @@ zend_array *__zend_new_array__(uint32_t size); bool is_internal_class(zend_class_entry *entry); zend_string *__zval_serialize__(zend_object *obj); void __zval_unserialize__(zval *retval, zend_string *str); -zend_object *__php_object_init__( - zval *zv, - const char *class_name, - size_t class_name_len, - zend_class_entry *ce -); +zend_object *__php_object_init__(zval *zv, const char *class_name, + size_t class_name_len, zend_class_entry *ce); #endif diff --git a/types_test.go b/types_test.go index 7f5c902e..b3731232 100644 --- a/types_test.go +++ b/types_test.go @@ -2,6 +2,7 @@ package frankenphp import ( "errors" + "fmt" "io" "log/slog" "testing" @@ -211,8 +212,8 @@ func BenchmarkFloat(b *testing.B) { } func BenchmarkString(b *testing.B) { + message := "Hello, World!" benchOnPHPThread(b, b.N, func() { - message := "Hello, World!" phpString := PHPString(message, false) _ = GoString(phpString) zendStringRelease(phpString) @@ -220,15 +221,26 @@ func BenchmarkString(b *testing.B) { } func BenchmarkMap(b *testing.B) { + originalMap := map[string]any{ + "foo1": "bar1", + "foo2": int64(2), + "foo3": true, + "foo4": 3.14, + "foo5": nil, + } benchOnPHPThread(b, b.N, func() { - originalMap := map[string]any{ - "foo1": "bar1", - "foo2": int64(2), - "foo3": true, - "foo4": 3.14, - "foo5": nil, - } + phpArray := PHPMap(originalMap) + _ = GoMap(phpArray) + zendHashDestroy(phpArray) + }) +} +func BenchmarkMap50Entries(b *testing.B) { + originalMap := map[string]any{} + for i := 0; i < 50; i++ { + originalMap[fmt.Sprintf("key%d", i)] = fmt.Sprintf("value%d", i) + } + benchOnPHPThread(b, b.N, func() { phpArray := PHPMap(originalMap) _ = GoMap(phpArray) zendHashDestroy(phpArray) @@ -236,18 +248,17 @@ func BenchmarkMap(b *testing.B) { } func BenchmarkOrderedAssociativeArray(b *testing.B) { + originalArray := AssociativeArray{ + Map: map[string]any{ + "foo1": "bar1", + "foo2": int64(2), + "foo3": true, + "foo4": 3.14, + "foo5": nil, + }, + Order: []string{"foo3", "foo1", "foo4", "foo2", "foo5"}, + } benchOnPHPThread(b, b.N, func() { - originalArray := AssociativeArray{ - Map: map[string]any{ - "foo1": "bar1", - "foo2": int64(2), - "foo3": true, - "foo4": 3.14, - "foo5": nil, - }, - Order: []string{"foo3", "foo1", "foo4", "foo2", "foo5"}, - } - phpArray := PHPAssociativeArray(originalArray) _ = GoAssociativeArray(phpArray) zendHashDestroy(phpArray) @@ -255,9 +266,8 @@ func BenchmarkOrderedAssociativeArray(b *testing.B) { } func BenchmarkSlice(b *testing.B) { + originalSlice := []any{"bar1", "bar2", "bar3", "bar4", "bar5"} benchOnPHPThread(b, b.N, func() { - originalSlice := []any{"bar1", "bar2", "bar3", "bar4", "bar5"} - phpArray := PHPPackedArray(originalSlice) _ = GoPackedArray(phpArray) zendHashDestroy(phpArray) @@ -265,18 +275,17 @@ func BenchmarkSlice(b *testing.B) { } func BenchmarkObject(b *testing.B) { + originalObject := Object{ + ClassName: "stdClass", + Props: map[string]any{ + "prop1": "value1", + "prop2": int64(42), + "prop3": true, + "prop4": 3.14, + "prop5": nil, + }, + } benchOnPHPThread(b, b.N, func() { - originalObject := Object{ - ClassName: "stdClass", - Props: map[string]any{ - "prop1": "value1", - "prop2": int64(42), - "prop3": true, - "prop4": 3.14, - "prop5": nil, - }, - } - phpObject := PHPObject(originalObject) _ = GoObject(phpObject) zvalPtrDtor(phpObject) @@ -284,12 +293,11 @@ func BenchmarkObject(b *testing.B) { } func BenchmarkEmptyObject(b *testing.B) { + originalObject := Object{ + ClassName: "stdClass", + Props: map[string]any{}, + } benchOnPHPThread(b, b.N, func() { - originalObject := Object{ - ClassName: "stdClass", - Props: map[string]any{}, - } - phpObject := PHPObject(originalObject) _ = GoObject(phpObject) zvalPtrDtor(phpObject)