Skip to content

Commit 6c5942f

Browse files
committed
serialize() optimization
1 parent 17ad94d commit 6c5942f

File tree

1 file changed

+88
-31
lines changed

1 file changed

+88
-31
lines changed

ext/standard/var.c

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,7 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) /
651651

652652
data->n += 1;
653653

654-
if (!is_ref && Z_TYPE_P(var) != IS_OBJECT) {
654+
if (!is_ref && (Z_TYPE_P(var) != IS_OBJECT || Z_REFCOUNT_P(var) == 1)) {
655655
return 0;
656656
}
657657

@@ -691,32 +691,62 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var) /
691691

692692
static inline void php_var_serialize_long(smart_str *buf, zend_long val) /* {{{ */
693693
{
694-
smart_str_appendl(buf, "i:", 2);
695-
smart_str_append_long(buf, val);
696-
smart_str_appendc(buf, ';');
694+
char b[32];
695+
char *s = zend_print_long_to_buf(b + sizeof(b) - 1, val);
696+
size_t l = b + sizeof(b) - 1 - s;
697+
size_t new_len = smart_str_alloc(buf, 2 + l + 1, 0);
698+
char *res = ZSTR_VAL(buf->s) + ZSTR_LEN(buf->s);
699+
700+
ZSTR_LEN(buf->s) = new_len;
701+
memcpy(res, "i:", 2);
702+
res += 2;
703+
memcpy(res, s, l);
704+
res[l] = ';';
697705
}
698706
/* }}} */
699707

700708
static inline void php_var_serialize_string(smart_str *buf, char *str, size_t len) /* {{{ */
701709
{
702-
smart_str_appendl(buf, "s:", 2);
703-
smart_str_append_unsigned(buf, len);
704-
smart_str_appendl(buf, ":\"", 2);
705-
smart_str_appendl(buf, str, len);
706-
smart_str_appendl(buf, "\";", 2);
710+
char b[32];
711+
char *s = zend_print_long_to_buf(b + sizeof(b) - 1, len);
712+
size_t l = b + sizeof(b) - 1 - s;
713+
size_t new_len = smart_str_alloc(buf, 2 + l + 2 + len + 2, 0);
714+
char *res = ZSTR_VAL(buf->s) + ZSTR_LEN(buf->s);
715+
716+
ZSTR_LEN(buf->s) = new_len;
717+
memcpy(res, "s:", 2);
718+
res += 2;
719+
memcpy(res, s, l);
720+
res += l;
721+
memcpy(res, ":\"", 2);
722+
res += 2;
723+
memcpy(res, str, len);
724+
res += len;
725+
memcpy(res, "\";", 2);
707726
}
708727
/* }}} */
709728

710729
static inline bool php_var_serialize_class_name(smart_str *buf, zval *struc) /* {{{ */
711730
{
731+
char b[32], *s, *res;
732+
size_t l, new_len;
712733
PHP_CLASS_ATTRIBUTES;
713734

714735
PHP_SET_CLASS_ATTRIBUTES(struc);
715-
smart_str_appendl(buf, "O:", 2);
716-
smart_str_append_unsigned(buf, ZSTR_LEN(class_name));
717-
smart_str_appendl(buf, ":\"", 2);
718-
smart_str_append(buf, class_name);
719-
smart_str_appendl(buf, "\":", 2);
736+
s = zend_print_long_to_buf(b + sizeof(b) - 1, ZSTR_LEN(class_name));
737+
l = b + sizeof(b) - 1 - s;
738+
new_len = smart_str_alloc(buf, 2 + l + 2 + ZSTR_LEN(class_name) + 2, 0);
739+
res = ZSTR_VAL(buf->s) + ZSTR_LEN(buf->s);
740+
ZSTR_LEN(buf->s) = new_len;
741+
memcpy(res, "O:", 2);
742+
res += 2;
743+
memcpy(res, s, l);
744+
res += l;
745+
memcpy(res, ":\"", 2);
746+
res += 2;
747+
memcpy(res, ZSTR_VAL(class_name), ZSTR_LEN(class_name));
748+
res += ZSTR_LEN(class_name);
749+
memcpy(res, "\":", 2);
720750
PHP_CLEANUP_CLASS_ATTRIBUTES();
721751
return incomplete_class;
722752
}
@@ -992,11 +1022,19 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
9921022
return;
9931023

9941024
case IS_DOUBLE: {
995-
char tmp_str[PHP_DOUBLE_MAX_LENGTH];
996-
smart_str_appendl(buf, "d:", 2);
1025+
char tmp_str[PHP_DOUBLE_MAX_LENGTH], *res;
1026+
size_t len, new_len;
1027+
9971028
php_gcvt(Z_DVAL_P(struc), (int)PG(serialize_precision), '.', 'E', tmp_str);
998-
smart_str_appends(buf, tmp_str);
999-
smart_str_appendc(buf, ';');
1029+
len = strlen(tmp_str);
1030+
new_len = smart_str_alloc(buf, 2 + len + 1, 0);
1031+
res = ZSTR_VAL(buf->s) + ZSTR_LEN(buf->s);
1032+
ZSTR_LEN(buf->s) = new_len;
1033+
1034+
memcpy(res, "d:", 2);
1035+
res += 2;
1036+
memcpy(res, tmp_str, len);
1037+
res[len] = ';';
10001038
return;
10011039
}
10021040

@@ -1025,9 +1063,9 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
10251063
}
10261064

10271065
php_var_serialize_class_name(buf, &obj);
1028-
smart_str_append_unsigned(buf, zend_array_count(Z_ARRVAL(retval)));
1066+
smart_str_append_unsigned(buf, zend_hash_num_elements(Z_ARRVAL(retval)));
10291067
smart_str_appendl(buf, ":{", 2);
1030-
ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(retval), index, key, data) {
1068+
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(retval), index, key, data) {
10311069
if (!key) {
10321070
php_var_serialize_long(buf, index);
10331071
} else {
@@ -1052,21 +1090,40 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
10521090
size_t serialized_length;
10531091

10541092
if (ce->serialize(struc, &serialized_data, &serialized_length, (zend_serialize_data *)var_hash) == SUCCESS) {
1055-
smart_str_appendl(buf, "C:", 2);
1056-
smart_str_append_unsigned(buf, ZSTR_LEN(Z_OBJCE_P(struc)->name));
1057-
smart_str_appendl(buf, ":\"", 2);
1058-
smart_str_append(buf, Z_OBJCE_P(struc)->name);
1059-
smart_str_appendl(buf, "\":", 2);
1060-
1061-
smart_str_append_unsigned(buf, serialized_length);
1062-
smart_str_appendl(buf, ":{", 2);
1063-
smart_str_appendl(buf, (char *) serialized_data, serialized_length);
1064-
smart_str_appendc(buf, '}');
1093+
char b1[32], b2[32], *s1, *s2, *res;
1094+
size_t l1, l2, new_len;
1095+
1096+
s1 = zend_print_long_to_buf(b1 + sizeof(b1) - 1, ZSTR_LEN(Z_OBJCE_P(struc)->name));
1097+
l1 = b1 + sizeof(b1) - 1 - s1;
1098+
s2 = zend_print_long_to_buf(b2 + sizeof(b2) - 1, serialized_length);
1099+
l2 = b2 + sizeof(b2) - 1 - s2;
1100+
new_len = smart_str_alloc(buf, 2 + l1 + 2 + ZSTR_LEN(Z_OBJCE_P(struc)->name) + 2 + l2 + 2 + serialized_length + 1, 0);
1101+
res = ZSTR_VAL(buf->s) + ZSTR_LEN(buf->s);
1102+
ZSTR_LEN(buf->s) = new_len;
1103+
memcpy(res, "C:", 2);
1104+
res += 2;
1105+
memcpy(res, s1, l1);
1106+
res += l1;
1107+
memcpy(res, ":\"", 2);
1108+
res += 2;
1109+
memcpy(res, ZSTR_VAL(Z_OBJCE_P(struc)->name), ZSTR_LEN(Z_OBJCE_P(struc)->name));
1110+
res += ZSTR_LEN(Z_OBJCE_P(struc)->name);
1111+
memcpy(res, "\":", 2);
1112+
res += 2;
1113+
1114+
memcpy(res, s2, l2);
1115+
res += l2;
1116+
memcpy(res, ":{", 2);
1117+
res += 2;
1118+
memcpy(res, (char *) serialized_data, serialized_length);
1119+
res[serialized_length] = '}';
10651120
} else {
10661121
/* Mark this value in the var_hash, to avoid creating references to it. */
10671122
zval *var_idx = zend_hash_index_find(&var_hash->ht,
10681123
(zend_ulong) (zend_uintptr_t) Z_COUNTED_P(struc));
1069-
ZVAL_LONG(var_idx, -1);
1124+
if (var_idx) {
1125+
ZVAL_LONG(var_idx, -1);
1126+
}
10701127
smart_str_appendl(buf, "N;", 2);
10711128
}
10721129
if (serialized_data) {

0 commit comments

Comments
 (0)