summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-07-14 22:09:39 +0200
committerBram Moolenaar <Bram@vim.org>2016-07-14 22:09:39 +0200
commit480778b805bd8bdc5d657560230e9c50feda1d0f (patch)
tree6805c47f6267ff72c16b9a3833b625b8693bb861
parentda4127794aa333631bde879e73bcfce4aef42f85 (diff)
patch 7.4.2036v7.4.2036
Problem: Looking up a buffer by number is slow if there are many. Solution: Use a hashtab.
-rw-r--r--src/buffer.c48
-rw-r--r--src/structs.h3
-rw-r--r--src/version.c2
3 files changed, 45 insertions, 8 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 9511d61597..65ab22fc83 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -350,6 +350,28 @@ buf_valid(buf_T *buf)
}
/*
+ * 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.
* "action" is used when there is no longer a window for the buffer.
* It can be:
@@ -723,6 +745,9 @@ free_buffer(buf_T *buf)
#endif
#ifdef FEAT_AUTOCMD
aubuflocal_remove(buf);
+
+ buf_hashtab_remove(buf);
+
if (autocmd_busy)
{
/* Do not free the buffer structure while autocommands are executing,
@@ -1703,6 +1728,8 @@ do_autochdir(void)
* functions for dealing with the buffer list
*/
+static int top_file_num = 1; /* highest file number */
+
/*
* Add a file name to the buffer list. Return a pointer to the buffer.
* If the same file name already exists return a pointer to that buffer.
@@ -1715,8 +1742,6 @@ do_autochdir(void)
* if the buffer already exists.
* This is the ONLY way to create a new buffer.
*/
-static int top_file_num = 1; /* highest file number */
-
buf_T *
buflist_new(
char_u *ffname, /* full path of fname or relative */
@@ -1729,6 +1754,9 @@ buflist_new(
stat_T st;
#endif
+ if (top_file_num == 1)
+ hash_init(&buf_hashtab);
+
fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */
/*
@@ -1907,6 +1935,7 @@ buflist_new(
}
top_file_num = 1;
}
+ buf_hashtab_add(buf);
/*
* Always copy the options from the current buffer.
@@ -2579,19 +2608,22 @@ fname_match(
#endif
/*
- * find file in buffer list by number
+ * Find a file in the buffer list by buffer number.
*/
buf_T *
buflist_findnr(int nr)
{
- buf_T *buf;
+ char_u key[VIM_SIZEOF_INT * 2 + 1];
+ hashitem_T *hi;
if (nr == 0)
nr = curwin->w_alt_fnum;
- /* Assume newer buffers are used more often, start from the end. */
- for (buf = lastbuf; buf != NULL; buf = buf->b_prev)
- if (buf->b_fnum == nr)
- return buf;
+ sprintf((char *)key, "%x", nr);
+ hi = hash_find(&buf_hashtab, key);
+
+ if (!HASHITEM_EMPTY(hi))
+ return (buf_T *)(hi->hi_key
+ - ((unsigned)(curbuf->b_key - (char_u *)curbuf)));
return NULL;
}
diff --git a/src/structs.h b/src/structs.h
index 0cf2800614..97e4e97cb9 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1753,6 +1753,9 @@ struct file_buffer
unsigned int b_fab_mrs; /* Max record size */
#endif
int b_fnum; /* buffer number for this file. */
+ char_u b_key[VIM_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
file has been changed and not written out. */
diff --git a/src/version.c b/src/version.c
index 0dfb7593b8..23a5993adf 100644
--- a/src/version.c
+++ b/src/version.c
@@ -759,6 +759,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2036,
+/**/
2035,
/**/
2034,