vim-patch:7.4.2036

Problem:    Looking up a buffer by number is slow if there are many.
Solution:   Use a hashtab.

480778b805
This commit is contained in:
lonerover 2017-01-03 12:19:19 +08:00
parent efe1476d42
commit a5f36e24bb
3 changed files with 39 additions and 8 deletions

View File

@ -279,6 +279,26 @@ bool buf_valid(buf_T *buf)
return false; return false;
} }
/// A hash table used to quickly lookup a buffer by its number.
static hashtab_T buf_hashtab;
static void buf_hashtab_add(buf_T *buf)
{
sprintf((char *)buf->b_key, "%x", buf->b_fnum);
if (hash_add(&buf_hashtab, buf->b_key) == FAIL) {
EMSG(_("E931: Buffer cannot be registered"));
}
}
static void buf_hashtab_remove(buf_T *buf)
{
hashitem_T *hi = hash_find(&buf_hashtab, buf->b_key);
if (!HASHITEM_EMPTY(hi)) {
hash_remove(&buf_hashtab, hi);
}
}
/// Close the link to a buffer. /// Close the link to a buffer.
/// ///
/// @param win If not NULL, set b_last_cursor. /// @param win If not NULL, set b_last_cursor.
@ -580,6 +600,7 @@ static void free_buffer(buf_T *buf)
free_buffer_stuff(buf, TRUE); free_buffer_stuff(buf, TRUE);
unref_var_dict(buf->b_vars); unref_var_dict(buf->b_vars);
aubuflocal_remove(buf); aubuflocal_remove(buf);
buf_hashtab_remove(buf);
dict_unref(buf->additional_data); dict_unref(buf->additional_data);
clear_fmark(&buf->b_last_cursor); clear_fmark(&buf->b_last_cursor);
clear_fmark(&buf->b_last_insert); clear_fmark(&buf->b_last_insert);
@ -1364,6 +1385,9 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
{ {
buf_T *buf; buf_T *buf;
if (top_file_num == 1) {
hash_init(&buf_hashtab);
}
fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */
/* /*
@ -1488,6 +1512,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
} }
top_file_num = 1; top_file_num = 1;
} }
buf_hashtab_add(buf);
/* /*
* Always copy the options from the current buffer. * Always copy the options from the current buffer.
@ -1997,19 +2022,22 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case)
return match; return match;
} }
/* /// Find a file in the buffer list by buffer number.
* find file in buffer list by number
*/
buf_T *buflist_findnr(int nr) buf_T *buflist_findnr(int nr)
{ {
char_u key[SIZEOF_INT * 2 + 1];
hashitem_T *hi;
if (nr == 0) { if (nr == 0) {
nr = curwin->w_alt_fnum; nr = curwin->w_alt_fnum;
} }
FOR_ALL_BUFFERS(buf) { sprintf((char *)key, "%x", nr);
if (buf->b_fnum == nr) { hi = hash_find(&buf_hashtab, key);
return buf;
} if (!HASHITEM_EMPTY(hi)) {
return (buf_T *)(hi->hi_key
- ((unsigned)(curbuf->b_key - (char_u *)curbuf)));
} }
return NULL; return NULL;
} }

View File

@ -490,6 +490,9 @@ struct file_buffer {
bool file_id_valid; bool file_id_valid;
FileID file_id; FileID file_id;
char_u b_key[SIZEOF_INT * 2 + 1]; // key used for buf_hashtab, holds
// b_fnum as hex string
int b_changed; // 'modified': Set to true if something in the int b_changed; // 'modified': Set to true if something in the
// file has been changed and not written out. // file has been changed and not written out.
int b_changedtick; // incremented for each change, also for undo int b_changedtick; // incremented for each change, also for undo

View File

@ -404,7 +404,7 @@ static int included_patches[] = {
// 2039 NA // 2039 NA
// 2038 NA // 2038 NA
// 2037 NA // 2037 NA
// 2036, 2036,
// 2035 NA // 2035 NA
// 2034 NA // 2034 NA
2033, 2033,