| To: vim-dev@vim.org |
| Subject: Patch 7.1.235 |
| Fcc: outbox |
| From: Bram Moolenaar <Bram@moolenaar.net> |
| Mime-Version: 1.0 |
| Content-Type: text/plain; charset=ISO-8859-1 |
| Content-Transfer-Encoding: 8bit |
| |
| |
| Patch 7.1.235 |
| Problem: Pattern matching is slow when using a lot of simple patterns. |
| Solution: Avoid allocating memory by not freeing it when it's not so much. |
| (Alexei Alexandrov) |
| Files: src/regexp.c |
| |
| |
| |
| |
| |
| *** 378,391 **** |
| |
| static char_u *reg_prev_sub = NULL; |
| |
| - #if defined(EXITFREE) || defined(PROTO) |
| - void |
| - free_regexp_stuff() |
| - { |
| - vim_free(reg_prev_sub); |
| - } |
| - #endif |
| - |
| /* |
| * REGEXP_INRANGE contains all characters which are always special in a [] |
| * range after '\'. |
| --- 378,383 ---- |
| |
| *** 3206,3217 **** |
| } backpos_T; |
| |
| /* |
| ! * regstack and backpos are used by regmatch(). They are kept over calls to |
| ! * avoid invoking malloc() and free() often. |
| */ |
| ! static garray_T regstack; /* stack with regitem_T items, sometimes |
| ! preceded by regstar_T or regbehind_T. */ |
| ! static garray_T backpos; /* table with backpos_T for BACK */ |
| |
| /* |
| * Get pointer to the line "lnum", which is relative to "reg_firstlnum". |
| --- 3198,3236 ---- |
| } backpos_T; |
| |
| /* |
| ! * "regstack" and "backpos" are used by regmatch(). They are kept over calls |
| ! * to avoid invoking malloc() and free() often. |
| ! * "regstack" is a stack with regitem_T items, sometimes preceded by regstar_T |
| ! * or regbehind_T. |
| ! * "backpos_T" is a table with backpos_T for BACK |
| ! */ |
| ! static garray_T regstack = {0, 0, 0, 0, NULL}; |
| ! static garray_T backpos = {0, 0, 0, 0, NULL}; |
| ! |
| ! /* |
| ! * Both for regstack and backpos tables we use the following strategy of |
| ! * allocation (to reduce malloc/free calls): |
| ! * - Initial size is fairly small. |
| ! * - When needed, the tables are grown bigger (8 times at first, double after |
| ! * that). |
| ! * - After executing the match we free the memory only if the array has grown. |
| ! * Thus the memory is kept allocated when it's at the initial size. |
| ! * This makes it fast while not keeping a lot of memory allocated. |
| ! * A three times speed increase was observed when using many simple patterns. |
| */ |
| ! #define REGSTACK_INITIAL 2048 |
| ! #define BACKPOS_INITIAL 64 |
| ! |
| ! #if defined(EXITFREE) || defined(PROTO) |
| ! void |
| ! free_regexp_stuff() |
| ! { |
| ! ga_clear(®stack); |
| ! ga_clear(&backpos); |
| ! vim_free(reg_tofree); |
| ! vim_free(reg_prev_sub); |
| ! } |
| ! #endif |
| |
| /* |
| * Get pointer to the line "lnum", which is relative to "reg_firstlnum". |
| |
| *** 3346,3360 **** |
| char_u *s; |
| long retval = 0L; |
| |
| ! reg_tofree = NULL; |
| ! |
| ! /* Init the regstack empty. Use an item size of 1 byte, since we push |
| ! * different things onto it. Use a large grow size to avoid reallocating |
| ! * it too often. */ |
| ! ga_init2(®stack, 1, 10000); |
| ! |
| ! /* Init the backpos table empty. */ |
| ! ga_init2(&backpos, sizeof(backpos_T), 10); |
| |
| if (REG_MULTI) |
| { |
| --- 3365,3389 ---- |
| char_u *s; |
| long retval = 0L; |
| |
| ! /* Create "regstack" and "backpos" if they are not allocated yet. |
| ! * We allocate *_INITIAL amount of bytes first and then set the grow size |
| ! * to much bigger value to avoid many malloc calls in case of deep regular |
| ! * expressions. */ |
| ! if (regstack.ga_data == NULL) |
| ! { |
| ! /* Use an item size of 1 byte, since we push different things |
| ! * onto the regstack. */ |
| ! ga_init2(®stack, 1, REGSTACK_INITIAL); |
| ! ga_grow(®stack, REGSTACK_INITIAL); |
| ! regstack.ga_growsize = REGSTACK_INITIAL * 8; |
| ! } |
| ! |
| ! if (backpos.ga_data == NULL) |
| ! { |
| ! ga_init2(&backpos, sizeof(backpos_T), BACKPOS_INITIAL); |
| ! ga_grow(&backpos, BACKPOS_INITIAL); |
| ! backpos.ga_growsize = BACKPOS_INITIAL * 8; |
| ! } |
| |
| if (REG_MULTI) |
| { |
| |
| *** 3525,3533 **** |
| } |
| |
| theend: |
| ! vim_free(reg_tofree); |
| ! ga_clear(®stack); |
| ! ga_clear(&backpos); |
| |
| return retval; |
| } |
| --- 3554,3570 ---- |
| } |
| |
| theend: |
| ! /* Free "reg_tofree" when it's a bit big. |
| ! * Free regstack and backpos if they are bigger than their initial size. */ |
| ! if (reg_tofreelen > 400) |
| ! { |
| ! vim_free(reg_tofree); |
| ! reg_tofree = NULL; |
| ! } |
| ! if (regstack.ga_maxlen > REGSTACK_INITIAL) |
| ! ga_clear(®stack); |
| ! if (backpos.ga_maxlen > BACKPOS_INITIAL) |
| ! ga_clear(&backpos); |
| |
| return retval; |
| } |
| |
| *** 3717,3724 **** |
| #define RA_MATCH 4 /* successful match */ |
| #define RA_NOMATCH 5 /* didn't match */ |
| |
| ! /* Init the regstack and backpos table empty. They are initialized and |
| ! * freed in vim_regexec_both() to reduce malloc()/free() calls. */ |
| regstack.ga_len = 0; |
| backpos.ga_len = 0; |
| |
| --- 3754,3761 ---- |
| #define RA_MATCH 4 /* successful match */ |
| #define RA_NOMATCH 5 /* didn't match */ |
| |
| ! /* Make "regstack" and "backpos" empty. They are allocated and freed in |
| ! * vim_regexec_both() to reduce malloc()/free() calls. */ |
| regstack.ga_len = 0; |
| backpos.ga_len = 0; |
| |
| |
| |
| |
| *** 668,669 **** |
| --- 668,671 ---- |
| { /* Add new patch number below this line */ |
| + /**/ |
| + 235, |
| /**/ |
| |
| -- |
| NEIL INNES PLAYED: THE FIRST SELF-DESTRUCTIVE MONK, ROBIN'S LEAST FAVORITE |
| MINSTREL, THE PAGE CRUSHED BY A RABBIT, THE OWNER OF A DUCK |
| "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD |
| |
| /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ |
| /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ |
| \\\ download, build and distribute -- http://www.A-A-P.org /// |
| \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |