8000 Significantly optimize the redis_cmd_format_static() and redis_cmd_fo… · jrtkcoder/phpredis@053d62d · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 053d62d

Browse files
committed
Significantly optimize the redis_cmd_format_static() and redis_cmd_format() routines. In test cases the performance increase is 3-10 fold for these operations
1 parent 765b9a7 commit 053d62d

File tree

2 files changed

+114
-224
lines changed

2 files changed

+114
-224
lines changed

library.c

Lines changed: 114 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <sys/types.h>
44
#include <netinet/tcp.h> /* TCP_NODELAY */
55
#include <sys/socket.h>
6-
#include <ext/standard/php_smart_str_public.h>
6+
#include <ext/standard/php_smart_str.h>
77
#include <ext/standard/php_var.h>
88

99
#include "igbinary/igbinary.h"
@@ -185,242 +185,137 @@ void add_constant_long(zend_class_entry *ce, char *name, int value) {
185185

186186
int
187187
integer_length(int i) {
188-
int sz = 0;
189-
int ci = abs(i);
190-
while (ci>0) {
191-
ci = (ci/10);
192-
sz += 1;
193-
}
194-
if(i == 0) { /* log 0 doesn't make sense. */
195-
sz = 1;
196-
} else if(i < 0) { /* allow for neg sign as well. */
197-
sz++;
198-
}
199-
return sz;
200-
}
201-
202-
int
203-
double_length(double d) {
204-
char *s;
205-
int ret;
206-
s = _php_math_number_format(d, 8, '.', '\x00');
207-
ret = strlen(s);
208-
efree(s);
209-
return ret;
188+
int sz = 0;
189+
int ci = abs(i);
190+
while (ci > 0) {
191+
ci /= 10;
192+
sz++;
193+
}
194+
if (i == 0) { /* log 0 doesn't make sense. */
195+
sz = 1;
196+
} else if (i < 0) { /* allow for neg sign as well. */
197+
sz++;
198+
}
199+
return sz;
210200
}
211201

212-
213202
int
214203
redis_cmd_format_static(char **ret, char *keyword, char *format, ...) {
215204

216-
char *p, *s;
205+
char *p = format;
217206
va_list ap;
218-
219-
int total = 0, sz, ret_sz;
220-
int i;
221-
double dbl;
222-
223-
int stage; /* 0: count & alloc. 1: copy. */
224-
int elements = strlen(format);
225-
int keyword_len = strlen(keyword);
226-
int header_sz = 1 + integer_length(1 + elements) + 2 /* star + elements + CRLF */
227-
+ 1 + integer_length(keyword_len) + 2 /* dollar + command length + CRLF */
228-
+ keyword_len + 2; /* command + CRLF */
229-
230-
for(stage = 0; stage < 2; ++stage) {
231-
va_start(ap, format);
232-
if(stage == 0) {
233-
total = 0;
234-
} else {
235-
total = header_sz;
207+
smart_str buf = {0};
208+
int l = strlen(keyword);
209+
210+
va_start(ap, format);
211+
212+
/* add header */
213+
smart_str_appendc(&buf, '*');
214+
smart_str_append_long(&buf, strlen(format) + 1);
215+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
216+
smart_str_appendc(&buf, '$');
217+
smart_str_append_long(&buf, l);
218+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
219+
smart_str_appendl(&buf, keyword, l);
220+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
221+
222+
while (*p) {
223+
smart_str_appendc(&buf, '$');
224+
225+
switch(*p) {
226+
case 's': {
227+
char *val = va_arg(ap, char*);
228+
int val_len = va_arg(ap, int);
229+
smart_str_append_long(&buf, val_len);
230+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
231+
smart_str_appendl(&buf, val, val_len);
232+
}
233+
break;
234+
235+
case 'f':
236+
case 'F': {
237+
char tmp[100];
238+
double d = va_arg(ap, double);
239+
int tmp_len = snprintf(tmp, sizeof(tmp), "%.8f", d);
240+
smart_str_append_long(&buf, tmp_len);
241+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
242+
smart_str_appendl(&buf, tmp, tmp_len);
243+
}
244+
break;
245+
246+
case 'i':
247+
case 'd': {
248+
int i = va_arg(ap, int);
249+
char tmp[32];
250+
int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
251+
smart_str_append_long(&buf, tmp_len);
252+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
253+
smart_str_appendl(&buf, tmp, tmp_len);
254+
}
255+
break;
256+
}
257+
p++;
258+
smart_str_appendl(&buf, _NL, sizeof(_NL) - 1);
236259
}
237-
for(p = format; *p; ) {
238-
switch(*p) {
239-
case 's':
240-
s = va_arg(ap, char*);
241-
sz = va_arg(ap, int);
242-
if(stage == 1) {
243-
memcpy((*ret) + total, "$", 1); /* dollar */
244-
total++;
245-
246-
sprintf((*ret) + total, "%d", sz); /* size */
247-
total += integer_length(sz);
248-
249-
memcpy((*ret) + total, _NL, 2); /* CRLF */
250-
total += 2;
251-
252-
memcpy((*ret) + total, s, sz); /* string */
253-
total += sz;
254-
255-
memcpy((*ret) + total, _NL, 2); /* CRLF */
256-
total += 2;
257-
} else {
258-
total += 1 + integer_length(sz) + 2 + sz + 2;
259-
}
260-
break;
261-
262-
case 'F':
263-
case 'f':
264-
/* use spprintf here */
265-
dbl = va_arg(ap, double);
266-
sz = double_length(dbl);
267-
char *dbl_str;
268-
if(stage == 1) {
269-
memcpy((*ret) + total, "$", 1); /* dollar */
270-
total++;
271-
272-
sprintf((*ret) + total, "%d", sz); /* size */
273-
total += integer_length(sz);
274-
275-
memcpy((*ret) + total, _NL, 2); /* CRLF */
276-
total += 2;
277-
278-
/* float value */
279-
dbl_str = _php_math_number_format(dbl, 8, '.', '\x00');
280-
memcpy((*ret) + total, dbl_str, sz);
281-
efree(dbl_str);
282-
total += sz;
283-
284-
memcpy((*ret) + total, _NL, 2); /* CRLF */
285-
total += 2;
286-
} else {
287-
total += 1 + integer_length(sz) + 2 + sz + 2;
288-
}
289-
break;
290-
291-
case 'i':
292-
case 'd':
293-
i = va_arg(ap, int);
294-
/* compute display size of integer value */
295-
sz = integer_length(i);
296-
if(stage == 1) {
297-
memcpy((*ret) + total, "$", 1); /* dollar */
298-
total++;
299-
300-
sprintf((*ret) + total, "%d", sz); /* size */
301-
total += integer_length(sz);
302-
303-
memcpy((*ret) + total, _NL, 2); /* CRLF */
304-
total += 2;
305-
306-
sprintf((*ret) + total, "%d", i); /* int */
307-
total += sz;
308-
309-
memcpy((*ret) + total, _NL, 2); /* CRLF */
310-
total += 2;
311-
} else {
312-
total += 1 + integer_length(sz) + 2 + sz + 2;
313-
}
314-
break;
315-
}
316-
p++;
317-
}
318-
if(stage == 0) {
319-
ret_sz = total + header_sz;
320-
(*ret) = emalloc(ret_sz+1);
321-
sprintf(*ret, "*%d" _NL "$%d" _NL "%s" _NL, elements + 1, keyword_len, keyword);
322-
} else {
323-
(*ret)[ret_sz] = 0;
324-
// printf("cmd(%d)=[%s]\n", ret_sz, *ret);
325-
return ret_sz;
326-
}
327-
}
328-
return 0;
260+
smart_str_0(&buf);
261+
262+
*ret = buf.c;
263+
264+
return buf.len;
329265
}
330266

331267
/**
332268
* This command behave somehow like printf, except that strings need 2 arguments:
333269
* Their data and their size (strlen).
334270
* Supported formats are: %d, %i, %s
335271
*/
336-
//static /!\ problem with static commands !!
337272
int
338273
redis_cmd_format(char **ret, char *format, ...) {
339274

340-
char *p, *s;
341-
va_list ap;
275+
smart_str buf = {0};
276+
va_list ap;
277+
char *p = format;
278+
279+
while (*p) {
280+
if (*p == '%') {
281+
switch (*(++p)) {
282+
case 's': {
283+
char *tmp = va_arg(ap, char*);
284+
int tmp_len = va_arg(ap, int);
285+
smart_str_appendl(&buf, tmp, tmp_len);
286+
}
287+
break;
342288

343-
int total = 0, sz, ret_sz;
344-
int i, ci;
345-
double dbl;
346-
char *double_str;
347-
int double_len;
348-
349-
int stage; /* 0: count & alloc. 1: copy. */
350-
351-
for(stage = 0; stage < 2; ++stage) {
352-
va_start(ap, format);
353-
total = 0;
354-
for(p = format; *p; ) {
355-
356-
if(*p == '%') {
357-
switch(*(p+1)) {
358-
case 's':
359-
s = va_arg(ap, char*);
360-
sz = va_arg(ap, int);
361-
if(stage == 1) {
362-
memcpy((*ret) + total, s, sz);
363-
}
364-
total += sz;
365-
break;
366-
367-
case 'F':
368-
case 'f':
369-
/* use spprintf here */
370-
dbl = va_arg(ap, double);
371-
double_len = double_length(dbl);
372-
373-
if(stage == 1) {
374-
/* float value */
375-
char *dbl_str = _php_math_number_format(dbl, 8, '.', '\x00');
376-
memcpy((*ret) + total, dbl_str, sz);
377-
total += sz;
378-
efree(dbl_str);
379-
}
380-
total += double_len;
381-
efree(double_str);
382-
break;
383-
384-
case 'i':
385-
case 'd':
386-
i = va_arg(ap, int);
387-
/* compute display size of integer value */
388-
sz = 0;
389-
ci = abs(i);
390-
while (ci>0) {
391-
ci = (ci/10);
392-
sz += 1;
393-
}
394-
if(i == 0) { /* log 0 doesn't make sense. */
395-
sz = 1;
396-
} else if(i < 0) { /* allow for neg sign as well. */
397-
sz++;
398-
}
399-
if(stage == 1) {
400-
sprintf((*ret) + total, "%d", i);
401-
}
402-
total += sz;
403-
break;
404-
}
405-
p++;
406-
} else {
407-
if(stage == 1) {
408-
(*ret)[total] = *p;
409-
}
410-
total++;
411-
}
289+
case 'F':
290+
case 'f': {
291+
char tmp[100];
292+
double d = va_arg(ap, double);
293+
int tmp_len = snprintf(tmp, sizeof(tmp), "%.8f", d);
294+
smart_str_appendl(&buf, tmp, tmp_len);
295+
}
296+
break;
412297

413-
p++;
414-
}
415-
if(stage == 0) {
416-
ret_sz = total;
417-
(*ret) = emalloc(ret_sz+1);
418-
} else {
419-
(*ret)[ret_sz] = 0;
420-
return ret_sz;
421-
}
422-
}
423-
return 0;
298+
case 'd':
299+
case 'i': {
300+
int i = va_arg(ap, int);
301+
char tmp[32];
302+
int tmp_len = snprintf(tmp, sizeof(tmp), "%d", i);
303+
smart_str_appendl(&buf, tmp, tmp_len);
304+
}
305+
break;
306+
}
307+
} else {
308+
smart_str_appendc(&buf, *p);
309+
}
310+
311+
p++;
312+
}
313+
314+
smart_str_0(&buf);
315+
316+
*ret = buf.c;
317+
318+
return buf.len;
424319
}
425320

426321
PHPAPI void redis_bulk_double_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx) {
@@ -742,7 +637,6 @@ PHPAPI void redis_ping_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_s
742637
RETURN_FALSE;
743638
}
744639
IF_MULTI_OR_PIPELINE() {
745-
zval *z = NULL;
746640
add_next_index_stringl(z_tab, response, response_len, 0);
747641
} else {
748642
RETURN_STRINGL(response, response_len, 0);
@@ -759,15 +653,12 @@ PHPAPI RedisSock* redis_sock_create(char *host, int host_len, unsigned short por
759653
RedisSock *redis_sock;
760654

761655
redis_sock = ecalloc(1, sizeof(RedisSock));
762-
redis_sock->host = ecalloc(host_len + 1, 1);
656+
redis_sock->host = strndup(host, host_len);
763657
redis_sock->stream = NULL;
764658
redis_sock->status = REDIS_SOCK_STATUS_DISCONNECTED;
765659

766660
redis_sock->persistent = persistent;
767661

768-
memcpy(redis_sock->host, host, host_len);
769-
redis_sock->host[host_len] = '\0';
770-
771662
redis_sock->port = port;
772663
redis_sock->timeout = timeout;
773664

library.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
void add_constant_long(zend_class_entry *ce, char *name, int value);
22
int integer_length(int i);
3-
int double_length(double d);
43
int redis_cmd_format(char **ret, char *format, ...);
54
int redis_cmd_format_static(char **ret, char *keyword, char *format, ...);
65

0 commit comments

Comments
 (0)
0