# HG changeset patch # User Christian Brabandt # Date 1452180609 -3600 # Node ID a64793340689d0657962ca1f160e1c73895af666 # Parent 3eda97270667925f62c6f85d26a639d599871480 commit https://github.com/vim/vim/commit/ca1fe985175385c609f8e06672a1014729aba05c Author: Bram Moolenaar Date: Thu Jan 7 16:22:06 2016 +0100 patch 7.4.1056 Problem: Don't know why finding spell suggestions is slow. Solution: Add some code to gather profiling information. diff --git a/src/spell.c b/src/spell.c --- a/src/spell.c +++ b/src/spell.c @@ -11279,6 +11279,56 @@ suggest_try_special(su) } /* + * Change the 0 to 1 to measure how much time is spent in each state. + * Output is dumped in "suggestprof". + */ +#if 0 +# define SUGGEST_PROFILE +proftime_T current; +proftime_T total; +proftime_T times[STATE_FINAL + 1]; +long counts[STATE_FINAL + 1]; + + static void +prof_init(void) +{ + for (int i = 0; i <= STATE_FINAL; ++i) + { + profile_zero(×[i]); + counts[i] = 0; + } + profile_start(¤t); + profile_start(&total); +} + +/* call before changing state */ + static void +prof_store(state_T state) +{ + profile_end(¤t); + profile_add(×[state], ¤t); + ++counts[state]; + profile_start(¤t); +} +# define PROF_STORE(state) prof_store(state); + + static void +prof_report(char *name) +{ + FILE *fd = fopen("suggestprof", "a"); + + profile_end(&total); + fprintf(fd, "-----------------------\n"); + fprintf(fd, "%s: %s\n", name, profile_msg(&total)); + for (int i = 0; i <= STATE_FINAL; ++i) + fprintf(fd, "%d: %s (%ld)\n", i, profile_msg(×[i]), counts[i]); + fclose(fd); +} +#else +# define PROF_STORE(state) +#endif + +/* * Try finding suggestions by adding/removing/swapping letters. */ static void @@ -11309,7 +11359,13 @@ suggest_try_change(su) continue; /* Try it for this language. Will add possible suggestions. */ +#ifdef SUGGEST_PROFILE + prof_init(); +#endif suggest_trie_walk(su, lp, fword, FALSE); +#ifdef SUGGEST_PROFILE + prof_report("try_change"); +#endif } } @@ -11467,6 +11523,7 @@ suggest_trie_walk(su, lp, fword, soundfo /* Always past NUL bytes now. */ n = (int)sp->ts_state; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; sp->ts_save_badflags = su->su_badflags; @@ -11510,6 +11567,7 @@ suggest_trie_walk(su, lp, fword, soundfo if (sp->ts_curi > len || byts[arridx] != 0) { /* Past bytes in node and/or past NUL bytes. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_ENDNUL; sp->ts_save_badflags = su->su_badflags; break; @@ -11909,6 +11967,7 @@ suggest_trie_walk(su, lp, fword, soundfo #endif /* Save things to be restored at STATE_SPLITUNDO. */ sp->ts_save_badflags = su->su_badflags; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SPLITUNDO; ++depth; @@ -11983,6 +12042,7 @@ suggest_trie_walk(su, lp, fword, soundfo byts = pbyts; idxs = pidxs; sp->ts_prefixdepth = PFD_PREFIXTREE; + PROF_STORE(sp->ts_state) sp->ts_state = STATE_NOPREFIX; } } @@ -11995,6 +12055,7 @@ suggest_trie_walk(su, lp, fword, soundfo su->su_badflags = sp->ts_save_badflags; /* Continue looking for NUL bytes. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_START; /* In case we went into the prefix tree. */ @@ -12012,9 +12073,11 @@ suggest_trie_walk(su, lp, fword, soundfo ) { /* The badword ends, can't use STATE_PLAIN. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_DEL; break; } + PROF_STORE(sp->ts_state) sp->ts_state = STATE_PLAIN; /*FALLTHROUGH*/ @@ -12028,6 +12091,7 @@ suggest_trie_walk(su, lp, fword, soundfo { /* Done all bytes at this node, do next state. When still at * already changed bytes skip the other tricks. */ + PROF_STORE(sp->ts_state) if (sp->ts_fidx >= sp->ts_fidxtry) sp->ts_state = STATE_DEL; else @@ -12184,6 +12248,7 @@ suggest_trie_walk(su, lp, fword, soundfo * delete/insert/swap a character. */ if (has_mbyte && sp->ts_tcharlen > 0) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } @@ -12191,6 +12256,7 @@ suggest_trie_walk(su, lp, fword, soundfo /* * Try skipping one character in the bad word (delete it). */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_INS_PREP; sp->ts_curi = 1; if (soundfold && sp->ts_fidx == 0 && fword[sp->ts_fidx] == '*') @@ -12245,6 +12311,7 @@ suggest_trie_walk(su, lp, fword, soundfo { /* If we just deleted a byte then inserting won't make sense, * a substitute is always cheaper. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } @@ -12256,12 +12323,14 @@ suggest_trie_walk(su, lp, fword, soundfo if (sp->ts_curi > byts[n]) { /* Only NUL bytes at this node, go to next state. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } if (byts[n + sp->ts_curi] != NUL) { /* Found a byte to insert. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_INS; break; } @@ -12278,6 +12347,7 @@ suggest_trie_walk(su, lp, fword, soundfo if (sp->ts_curi > byts[n]) { /* Done all bytes at this node, go to next state. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP; break; } @@ -12349,6 +12419,7 @@ suggest_trie_walk(su, lp, fword, soundfo if (c == NUL) { /* End of word, can't swap or replace. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } @@ -12357,6 +12428,7 @@ suggest_trie_walk(su, lp, fword, soundfo * SWAP3 etc. also don't make sense then. */ if (!soundfold && !spell_iswordp(p, curwin)) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -12387,6 +12459,7 @@ suggest_trie_walk(su, lp, fword, soundfo /* When the second character is NUL we can't swap. */ if (c2 == NUL) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -12395,6 +12468,7 @@ suggest_trie_walk(su, lp, fword, soundfo * Also get here if the second char is not a word character. */ if (c == c2) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_SWAP3; break; } @@ -12406,6 +12480,7 @@ suggest_trie_walk(su, lp, fword, soundfo sp->ts_twordlen, tword, fword + sp->ts_fidx, c, c2); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP; ++depth; #ifdef FEAT_MBYTE @@ -12425,8 +12500,11 @@ suggest_trie_walk(su, lp, fword, soundfo } } else + { /* If this swap doesn't work then SWAP3 won't either. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNSWAP: @@ -12484,6 +12562,7 @@ suggest_trie_walk(su, lp, fword, soundfo * Second character may any char: "a.b" -> "b.a" */ if (c == c3 || c3 == NUL) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -12495,6 +12574,7 @@ suggest_trie_walk(su, lp, fword, soundfo sp->ts_twordlen, tword, fword + sp->ts_fidx, c, c3); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNSWAP3; ++depth; #ifdef FEAT_MBYTE @@ -12515,7 +12595,10 @@ suggest_trie_walk(su, lp, fword, soundfo } } else + { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNSWAP3: @@ -12547,6 +12630,7 @@ suggest_trie_walk(su, lp, fword, soundfo { /* Middle char is not a word char, skip the rotate. First and * third char were already checked at swap and swap3. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; break; } @@ -12562,6 +12646,7 @@ suggest_trie_walk(su, lp, fword, soundfo sp->ts_twordlen, tword, fword + sp->ts_fidx, p[0], p[1], p[2]); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNROT3L; ++depth; p = fword + sp->ts_fidx; @@ -12587,7 +12672,10 @@ suggest_trie_walk(su, lp, fword, soundfo } } else + { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNROT3L: @@ -12623,6 +12711,7 @@ suggest_trie_walk(su, lp, fword, soundfo sp->ts_twordlen, tword, fword + sp->ts_fidx, p[0], p[1], p[2]); #endif + PROF_STORE(sp->ts_state) sp->ts_state = STATE_UNROT3R; ++depth; p = fword + sp->ts_fidx; @@ -12648,7 +12737,10 @@ suggest_trie_walk(su, lp, fword, soundfo } } else + { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_INI; + } break; case STATE_UNROT3R: @@ -12684,6 +12776,7 @@ suggest_trie_walk(su, lp, fword, soundfo || sp->ts_score + SCORE_REP >= su->su_maxscore || sp->ts_fidx < sp->ts_fidxtry) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } @@ -12697,10 +12790,12 @@ suggest_trie_walk(su, lp, fword, soundfo if (sp->ts_curi < 0) { + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; break; } + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP; /*FALLTHROUGH*/ @@ -12733,6 +12828,7 @@ suggest_trie_walk(su, lp, fword, soundfo ftp->ft_from, ftp->ft_to); #endif /* Need to undo this afterwards. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP_UNDO; /* Change the "from" to the "to" string. */ @@ -12754,8 +12850,11 @@ suggest_trie_walk(su, lp, fword, soundfo } if (sp->ts_curi >= gap->ga_len && sp->ts_state == STATE_REP) + { /* No (more) matches. */ + PROF_STORE(sp->ts_state) sp->ts_state = STATE_FINAL; + } break; @@ -12775,6 +12874,7 @@ suggest_trie_walk(su, lp, fword, soundfo repextra -= tl - fl; } mch_memmove(p, ftp->ft_from, fl); + PROF_STORE(sp->ts_state) sp->ts_state = STATE_REP; break; @@ -13287,7 +13387,13 @@ suggest_try_soundalike(su) /* try all kinds of inserts/deletes/swaps/etc. */ /* TODO: also soundfold the next words, so that we can try joining * and splitting */ +#ifdef SUGGEST_PROFILE + prof_init(); +#endif suggest_trie_walk(su, lp, salword, TRUE); +#ifdef SUGGEST_PROFILE + prof_report("soundalike"); +#endif } } } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -742,6 +742,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1056, +/**/ 1055, /**/ 1054,