From 6e1ee9474491096b6b7bf1c55af00972c3ba0e61 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 25 Oct 2017 19:04:16 +0300 Subject: [PATCH] Reduce smart_string related reallocations and make them Zend MM friendly. --- Zend/zend_smart_str.c | 41 +++++++++++++++++++++++++++++++++++++ Zend/zend_smart_string.h | 44 ++++++++-------------------------------- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c index b020fddbaa..8f142854d2 100644 --- a/Zend/zend_smart_str.c +++ b/Zend/zend_smart_str.c @@ -18,6 +18,7 @@ #include #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 diff --git a/Zend/zend_smart_string.h b/Zend/zend_smart_string.h index 12d755ee41..464e58e520 100644 --- a/Zend/zend_smart_string.h +++ b/Zend/zend_smart_string.h @@ -25,26 +25,7 @@ #include "zend_smart_string_public.h" #include -#ifndef SMART_STR_USE_REALLOC #include -#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 */ @@ -71,25 +52,18 @@ #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) { -- 2.50.1