To: vim-dev@vim.org Subject: Patch 7.1.235 Fcc: outbox From: Bram Moolenaar 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 *** ../vim-7.1.234/src/regexp.c Wed Jan 2 15:34:48 2008 --- src/regexp.c Fri Jan 18 20:35:21 2008 *************** *** 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; *** ../vim-7.1.234/src/version.c Fri Jan 18 17:39:10 2008 --- src/version.c Fri Jan 18 20:33:26 2008 *************** *** 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 ///