]> granicus.if.org Git - php/commitdiff
Optimize int to string conversion
authorNikita Popov <nikic@php.net>
Fri, 23 May 2014 11:10:50 +0000 (13:10 +0200)
committerNikita Popov <nikic@php.net>
Fri, 23 May 2014 11:10:50 +0000 (13:10 +0200)
Probably platform depedentant, but for me snprintf is terribly
slow.

The code for the long printing is taken from the smart string
API.

Zend/zend_operators.c
Zend/zend_operators.h
ext/standard/php_smart_str.h
ext/standard/php_smart_string.h

index 5fb88b1ca85ebc6e559d96a8621d9b0d10ceaa1b..b8ab22fc069b84abe879bbab8fd8b573ce32055f 100644 (file)
@@ -604,9 +604,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{{ */
                        break;
                }
                case IS_LONG: {
-                       char buf[MAX_LENGTH_OF_LONG + 1];
-                       int len = snprintf(buf, sizeof(buf), "%ld", Z_LVAL_P(op));
-                       ZVAL_NEW_STR(op, STR_INIT(buf, len, 0));
+                       ZVAL_NEW_STR(op, zend_long_to_str(Z_LVAL_P(op)));
                        break;
                }
                case IS_DOUBLE: {
@@ -883,11 +881,7 @@ try_again:
                        return STR_INIT(buf, len, 0);
                }
                case IS_LONG: {
-                       char buf[MAX_LENGTH_OF_LONG + 1];
-                       int len;
-
-                       len = snprintf(buf, sizeof(buf), "%ld", Z_LVAL_P(op));
-                       return STR_INIT(buf, len, 0);
+                       return zend_long_to_str(Z_LVAL_P(op));
                }
                case IS_DOUBLE: {
                        return zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(op));
@@ -2510,6 +2504,16 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) /* {{{ */
 }
 /* }}} */
 
+ZEND_API zend_string *zend_long_to_str(long num) /* {{{ */
+{
+       char buf[MAX_LENGTH_OF_LONG + 1];
+       char *res;
+       _zend_print_signed_to_buf(buf + sizeof(buf)-1, num, unsigned long, res);
+       return STR_INIT(res, buf + sizeof(buf)-1 - res, 0);
+}
+/* }}} */
+
+
 /*
  * Local variables:
  * tab-width: 4
index b7c8c7e7b2c831aa8a92d9a853703a4b27caa17d..f03e05b3ad8476282c50d8056ba5ef896c2adf1a 100644 (file)
@@ -964,6 +964,33 @@ static zend_always_inline void fast_is_not_identical_function(zval *result, zval
                return SUCCESS;                                                                           \
        }
 
+/* input: buf points to the END of the buffer */
+#define _zend_print_unsigned_to_buf(buf, num, vartype, result) do {    \
+       char *__p = (buf);                                                                                              \
+       vartype __num = (num);                                                                                  \
+       *__p = '\0';                                                                                                    \
+       do {                                                                                                                    \
+               *--__p = (char) (__num % 10) + '0';                                                     \
+               __num /= 10;                                                                                            \
+       } while (__num > 0);                                                                                    \
+       result = __p;                                                                                                   \
+} while (0)
+
+/* buf points to the END of the buffer */
+#define _zend_print_signed_to_buf(buf, num, vartype, result) do { \
+       if (num < 0) { \
+               /* this might cause problems when dealing with LONG_MIN
+                  and machines which don't support long long. Works
+                  flawlessly on 32bit x86 */ \
+               _zend_print_unsigned_to_buf((buf), -(num), vartype, (result)); \
+               *--(result) = '-'; \
+       } else { \
+               _zend_print_unsigned_to_buf((buf), (num), vartype, (result)); \
+       } \
+} while (0)
+
+ZEND_API zend_string *zend_long_to_str(long num);
+
 #endif
 
 /*
index 81b92d7a80be67c3842015310156f9e7af5e621e..e10a7114353be9f1929fbd586bc50ee999878674 100644 (file)
        __dest->s->len = __nl;                                                                                  \
 } while (0)
 
-/* input: buf points to the END of the buffer */
-#define smart_str_print_unsigned4(buf, num, vartype, result) do {      \
-       char *__p = (buf);                                                                                              \
-       vartype __num = (num);                                                                                  \
-       *__p = '\0';                                                                                                    \
-       do {                                                                                                                    \
-               *--__p = (char) (__num % 10) + '0';                                                     \
-               __num /= 10;                                                                                            \
-       } while (__num > 0);                                                                                    \
-       result = __p;                                                                                                   \
-} while (0)
-
-/* buf points to the END of the buffer */
-#define smart_str_print_long4(buf, num, vartype, result) do {          \
-       if (num < 0) {                                                                                                  \
-               /* this might cause problems when dealing with LONG_MIN         \
-                  and machines which don't support long long.  Works           \
-                  flawlessly on 32bit x86 */                                                           \
-               smart_str_print_unsigned4((buf), -(num), vartype, (result));\
-               *--(result) = '-';                                                                                      \
-       } else {                                                                                                                \
-               smart_str_print_unsigned4((buf), (num), vartype, (result));     \
-       }                                                                                                                               \
-} while (0)
-
 /*
  * these could be replaced using a braced-group inside an expression
  * for GCC compatible compilers, e.g.
  
 static inline char *smart_str_print_long(char *buf, long num) {
        char *r; 
-       smart_str_print_long4(buf, num, unsigned long, r); 
+       _zend_print_signed_to_buf(buf, num, unsigned long, r); 
        return r;
 }
 
 static inline char *smart_str_print_unsigned(char *buf, long num) {
        char *r; 
-       smart_str_print_unsigned4(buf, num, unsigned long, r); 
+       _zend_print_unsigned_to_buf(buf, num, unsigned long, r); 
        return r;
 }
 
 #define smart_str_append_generic_ex(dest, num, type, vartype, func) do {       \
        char __b[32];                                                                                                                   \
        char *__t;                                                                                                                              \
-       smart_str_print##func##4 (__b + sizeof(__b) - 1, (num), vartype, __t);  \
+       _zend_print##func##_to_buf (__b + sizeof(__b) - 1, (num), vartype, __t);        \
        smart_str_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type)); \
 } while (0)
        
@@ -178,10 +153,10 @@ static inline char *smart_str_print_unsigned(char *buf, long num) {
        smart_str_append_generic_ex((dest), (num), (type), unsigned long, _unsigned)
 
 #define smart_str_append_long_ex(dest, num, type) \
-       smart_str_append_generic_ex((dest), (num), (type), unsigned long, _long)
+       smart_str_append_generic_ex((dest), (num), (type), unsigned long, _signed)
 
 #define smart_str_append_off_t_ex(dest, num, type) \
-       smart_str_append_generic_ex((dest), (num), (type), off_t, _long)
+       smart_str_append_generic_ex((dest), (num), (type), off_t, _signed)
 
 #define smart_str_append_ex(dest, src, what)                                           \
        smart_str_appendl_ex((dest), ((smart_str *)(src))->s->val,              \
index 1613e4898b8f53a434ec2a6a892dce5c2cca0580..02ba9fe84e2a1616a474b045d749fe1917663c55 100644 (file)
        __dest->len = __nl;                                                                                             \
 } while (0)
 
-/* input: buf points to the END of the buffer */
-#define smart_string_print_unsigned4(buf, num, vartype, result) do {   \
-       char *__p = (buf);                                                                                              \
-       vartype __num = (num);                                                                                  \
-       *__p = '\0';                                                                                                    \
-       do {                                                                                                                    \
-               *--__p = (char) (__num % 10) + '0';                                                     \
-               __num /= 10;                                                                                            \
-       } while (__num > 0);                                                                                    \
-       result = __p;                                                                                                   \
-} while (0)
-
-/* buf points to the END of the buffer */
-#define smart_string_print_long4(buf, num, vartype, result) do {       \
-       if (num < 0) {                                                                                                  \
-               /* this might cause problems when dealing with LONG_MIN         \
-                  and machines which don't support long long.  Works           \
-                  flawlessly on 32bit x86 */                                                           \
-               smart_string_print_unsigned4((buf), -(num), vartype, (result)); \
-               *--(result) = '-';                                                                                      \
-       } else {                                                                                                                \
-               smart_string_print_unsigned4((buf), (num), vartype, (result));  \
-       }                                                                                                                               \
-} while (0)
-
-/*
- * these could be replaced using a braced-group inside an expression
- * for GCC compatible compilers, e.g.
- *
- * #define f(..) ({char *r;..;__r;})
- */  
 static inline char *smart_string_print_long(char *buf, long num) {
        char *r; 
-       smart_string_print_long4(buf, num, unsigned long, r); 
+       _zend_print_signed_to_buf(buf, num, unsigned long, r); 
        return r;
 }
 
 static inline char *smart_string_print_unsigned(char *buf, long num) {
        char *r; 
-       smart_string_print_unsigned4(buf, num, unsigned long, r); 
+       _zend_print_unsigned_to_buf(buf, num, unsigned long, r); 
        return r;
 }
 
 #define smart_string_append_generic_ex(dest, num, type, vartype, func) do {    \
        char __b[32];                                                                                                                   \
        char *__t;                                                                                                                              \
-       smart_string_print##func##4 (__b + sizeof(__b) - 1, (num), vartype, __t);       \
+       _zend_print##func##_to_buf(__b + sizeof(__b) - 1, (num), vartype, __t); \
        smart_string_appendl_ex((dest), __t, __b + sizeof(__b) - 1 - __t, (type));      \
 } while (0)
        
@@ -174,10 +142,10 @@ static inline char *smart_string_print_unsigned(char *buf, long num) {
        smart_string_append_generic_ex((dest), (num), (type), unsigned long, _unsigned)
 
 #define smart_string_append_long_ex(dest, num, type) \
-       smart_string_append_generic_ex((dest), (num), (type), unsigned long, _long)
+       smart_string_append_generic_ex((dest), (num), (type), unsigned long, _signed)
 
 #define smart_string_append_off_t_ex(dest, num, type) \
-       smart_string_append_generic_ex((dest), (num), (type), off_t, _long)
+       smart_string_append_generic_ex((dest), (num), (type), off_t, _signed)
 
 #define smart_string_append_ex(dest, src, what) \
        smart_string_appendl_ex((dest), ((smart_string *)(src))->c, \