]> granicus.if.org Git - php/commitdiff
Reduce smart_string related reallocations and make them Zend MM friendly.
authorDmitry Stogov <dmitry@zend.com>
Wed, 25 Oct 2017 16:04:16 +0000 (19:04 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 25 Oct 2017 16:04:16 +0000 (19:04 +0300)
Zend/zend_smart_str.c
Zend/zend_smart_string.h

index b020fddbaadfbf914f49819e81ba67f96d531718..8f142854d2e50674de839cc5fb8b79bd78bce64b 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <zend.h>
 #include "zend_smart_str.h"
+#include "zend_smart_string.h"
 
 #define SMART_STR_OVERHEAD (ZEND_MM_OVERHEAD + _ZSTR_HEADER_SIZE)
 
@@ -125,6 +126,46 @@ ZEND_API void ZEND_FASTCALL smart_str_append_printf(smart_str *dest, const char
        va_end(arg);
 }
 
+#define SMART_STRING_START_SIZE 255
+#define SMART_STRING_PREALLOC   128
+#define SMART_STRING_PAGE       4096
+
+ZEND_API void ZEND_FASTCALL _smart_string_alloc_persistent(smart_string *str, size_t len)
+{
+       if (!str->c) {
+               str->len = 0;
+               str->a = len <= SMART_STRING_START_SIZE
+                               ? SMART_STRING_START_SIZE
+                               : (ZEND_MM_ALIGNED_SIZE_EX(len + SMART_STRING_PREALLOC, SMART_STRING_PAGE) - 1);
+               str->c = malloc(str->a + 1);
+       } else {
+               if (UNEXPECTED((size_t) len > SIZE_MAX - str->len)) {
+                       zend_error(E_ERROR, "String size overflow");
+               }
+               len += str->len;
+               str->a = ZEND_MM_ALIGNED_SIZE_EX(len + SMART_STRING_PREALLOC, SMART_STRING_PAGE) - 1;
+               str->c = realloc(str->c, str->a + 1);
+       }
+}
+
+ZEND_API void ZEND_FASTCALL _smart_string_alloc(smart_string *str, size_t len)
+{
+       if (!str->c) {
+               str->len = 0;
+               str->a = len <= SMART_STRING_START_SIZE
+                               ? SMART_STRING_START_SIZE
+                               : (ZEND_MM_ALIGNED_SIZE_EX(len + SMART_STRING_PREALLOC, SMART_STRING_PAGE) - 1);
+               str->c = emalloc(str->a + 1);
+       } else {
+               if (UNEXPECTED((size_t) len > SIZE_MAX - str->len)) {
+                       zend_error(E_ERROR, "String size overflow");
+               }
+               len += str->len;
+               str->a = ZEND_MM_ALIGNED_SIZE_EX(len + SMART_STRING_PREALLOC, SMART_STRING_PAGE) - 1;
+               str->c = erealloc(str->c, str->a + 1);
+       }
+}
+
 /*
  * Local variables:
  * tab-width: 4
index 12d755ee4109759eee4dabcb558c58242cdbc0b2..464e58e5208c48f67de26e8c309962cf4734df8f 100644 (file)
 #include "zend_smart_string_public.h"
 
 #include <stdlib.h>
-#ifndef SMART_STR_USE_REALLOC
 #include <zend.h>
-#endif
-
-#ifndef SMART_STRING_PREALLOC
-#define SMART_STRING_PREALLOC 128
-#endif
-
-#ifndef SMART_STRING_START_SIZE
-#define SMART_STRING_START_SIZE 78
-#endif
-
-#ifdef SMART_STRING_USE_REALLOC
-#define SMART_STRING_REALLOC(a,b,c) realloc((a),(b))
-#else
-#define SMART_STRING_REALLOC(a,b,c) perealloc((a),(b),(c))
-#endif
-
-#define SMART_STRING_DO_REALLOC(d, what) \
-       (d)->c = (char *) SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
 
 /* wrapper */
 
 #define smart_string_append_unsigned(str, val) \
        smart_string_append_unsigned_ex((str), (val), 0)
 
+ZEND_API void ZEND_FASTCALL _smart_string_alloc_persistent(smart_string *str, size_t len);
+ZEND_API void ZEND_FASTCALL _smart_string_alloc(smart_string *str, size_t len);
+
 static zend_always_inline size_t smart_string_alloc(smart_string *str, size_t len, zend_bool persistent) {
-       if (!str->c) {
-               str->len = 0;
-               str->a = len < SMART_STRING_START_SIZE
-                               ? SMART_STRING_START_SIZE
-                               : len + SMART_STRING_PREALLOC;
-               SMART_STRING_DO_REALLOC(str, persistent);
-               return len;
-       } else {
-               if (UNEXPECTED((size_t) len > SIZE_MAX - str->len)) {
-                       zend_error(E_ERROR, "String size overflow");
-               }
-               len += str->len;
-               if (UNEXPECTED(len >= str->a)) {
-                       str->a = len + SMART_STRING_PREALLOC;
-                       SMART_STRING_DO_REALLOC(str, persistent);
+       if (UNEXPECTED(!str->c) || UNEXPECTED(len >= str->a - str->len)) {
+               if (persistent) {
+                       _smart_string_alloc_persistent(str, len);
+               } else {
+                       _smart_string_alloc(str, len);
                }
        }
-       return len;
+       return str->len + len;
 }
 
 static zend_always_inline void smart_string_free_ex(smart_string *str, zend_bool persistent) {