fix over-optimization of strstr

Tue, 04 Oct 2022 19:25:07 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 04 Oct 2022 19:25:07 +0200
changeset 591
7df0bcaecffa
parent 590
02a56701a5cb
child 592
bb69ef3ad1f3

fix over-optimization of strstr

1. it's actually less performant to frequently read bytes
from an array instead of using the native word length
2. the SBO buffer should be local and not static to allow
multi-threading usage

src/string.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/string.c	Tue Oct 04 18:55:20 2022 +0200
     1.2 +++ b/src/string.c	Tue Oct 04 19:25:07 2022 +0200
     1.3 @@ -227,14 +227,7 @@
     1.4      return (cxmutstr) {(char *) result.ptr, result.length};
     1.5  }
     1.6  
     1.7 -#define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \
     1.8 -    ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index])
     1.9 -
    1.10 -#define ptable_w(useheap, ptable, index, src) do {\
    1.11 -    if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\
    1.12 -    else ((size_t*)ptable)[index] = src;\
    1.13 -    } while (0)
    1.14 -
    1.15 +#define STRSTR_SBO_BUFLEN 512
    1.16  
    1.17  cxstring cx_strstr(
    1.18          cxstring haystack,
    1.19 @@ -257,14 +250,14 @@
    1.20       * and we want to avoid that.
    1.21       */
    1.22  
    1.23 -    /* static prefix table */
    1.24 -    static uint8_t s_prefix_table[512];
    1.25 +    /* local prefix table */
    1.26 +    size_t s_prefix_table[STRSTR_SBO_BUFLEN];
    1.27  
    1.28 -    /* check pattern length and use appropriate prefix table */
    1.29 +    /* check needle length and use appropriate prefix table */
    1.30      /* if the pattern exceeds static prefix table, allocate on the heap */
    1.31 -    register int useheap = needle.length >= 512;
    1.32 -    register void *ptable = useheap ? calloc(needle.length + 1,
    1.33 -                                             sizeof(size_t)) : s_prefix_table;
    1.34 +    bool useheap = needle.length >= STRSTR_SBO_BUFLEN;
    1.35 +    register size_t *ptable = useheap ? calloc(needle.length + 1,
    1.36 +                                               sizeof(size_t)) : s_prefix_table;
    1.37  
    1.38      /* keep counter in registers */
    1.39      register size_t i, j;
    1.40 @@ -272,14 +265,14 @@
    1.41      /* fill prefix table */
    1.42      i = 0;
    1.43      j = 0;
    1.44 -    ptable_w(useheap, ptable, i, j);
    1.45 +    ptable[i] = j;
    1.46      while (i < needle.length) {
    1.47          while (j >= 1 && needle.ptr[j - 1] != needle.ptr[i]) {
    1.48 -            ptable_r(j, useheap, ptable, j - 1);
    1.49 +            j = ptable[j - 1];
    1.50          }
    1.51          i++;
    1.52          j++;
    1.53 -        ptable_w(useheap, ptable, i, j);
    1.54 +        ptable[i] = j;
    1.55      }
    1.56  
    1.57      /* search */
    1.58 @@ -288,7 +281,7 @@
    1.59      j = 1;
    1.60      while (i < haystack.length) {
    1.61          while (j >= 1 && haystack.ptr[i] != needle.ptr[j - 1]) {
    1.62 -            ptable_r(j, useheap, ptable, j - 1);
    1.63 +            j = ptable[j - 1];
    1.64          }
    1.65          i++;
    1.66          j++;

mercurial