From a5f36e24bb294870516d89288968344c2d78f6b5 Mon Sep 17 00:00:00 2001 From: lonerover Date: Tue, 3 Jan 2017 12:19:19 +0800 Subject: vim-patch:7.4.2036 Problem: Looking up a buffer by number is slow if there are many. Solution: Use a hashtab. https://github.com/vim/vim/commit/480778b805bd8bdc5d657560230e9c50feda1d0f --- src/nvim/buffer.c | 42 +++++++++++++++++++++++++++++++++++------- src/nvim/buffer_defs.h | 3 +++ src/nvim/version.c | 2 +- 3 files changed, 39 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index d9fdc80c60..7b9876aa39 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -279,6 +279,26 @@ bool buf_valid(buf_T *buf) 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. /// /// @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); unref_var_dict(buf->b_vars); aubuflocal_remove(buf); + buf_hashtab_remove(buf); dict_unref(buf->additional_data); clear_fmark(&buf->b_last_cursor); 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; + if (top_file_num == 1) { + hash_init(&buf_hashtab); + } 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; } + buf_hashtab_add(buf); /* * 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; } -/* - * find file in buffer list by number - */ +/// Find a file in the buffer list by buffer number. buf_T *buflist_findnr(int nr) { + char_u key[SIZEOF_INT * 2 + 1]; + hashitem_T *hi; + if (nr == 0) { nr = curwin->w_alt_fnum; } - FOR_ALL_BUFFERS(buf) { - 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/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 2b66a07f48..f9d21b549a 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -490,6 +490,9 @@ struct file_buffer { bool file_id_valid; 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 // file has been changed and not written out. int b_changedtick; // incremented for each change, also for undo diff --git a/src/nvim/version.c b/src/nvim/version.c index f6f984bc8b..05267028ee 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -404,7 +404,7 @@ static int included_patches[] = { // 2039 NA // 2038 NA // 2037 NA - // 2036, + 2036, // 2035 NA // 2034 NA 2033, -- cgit From 1984e784fbba3757872eb396928ad919921ac6b1 Mon Sep 17 00:00:00 2001 From: lonerover Date: Tue, 3 Jan 2017 15:28:38 +0800 Subject: fix lint error --- src/nvim/buffer.c | 12 ++++++------ src/nvim/buffer_defs.h | 5 ++--- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 7b9876aa39..967c59ff8c 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -284,7 +284,7 @@ static hashtab_T buf_hashtab; static void buf_hashtab_add(buf_T *buf) { - sprintf((char *)buf->b_key, "%x", buf->b_fnum); + snprintf((char *)buf->b_key, sizeof(buf->b_key), "%x", buf->b_fnum); if (hash_add(&buf_hashtab, buf->b_key) == FAIL) { EMSG(_("E931: Buffer cannot be registered")); } @@ -1388,7 +1388,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) 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 /* * If file name already exists in the list, update the entry. @@ -2025,19 +2025,19 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case) /// Find a file in the buffer list by buffer number. buf_T *buflist_findnr(int nr) { - char_u key[SIZEOF_INT * 2 + 1]; + char_u key[sizeof(handle_T) * 2 + 1]; hashitem_T *hi; if (nr == 0) { nr = curwin->w_alt_fnum; } - sprintf((char *)key, "%x", nr); + snprintf((char *)key, sizeof(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 (buf_T *)(hi->hi_key - + ((unsigned)(curbuf->b_key - (char_u *)curbuf))); } return NULL; } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index f9d21b549a..353a2e0128 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -490,9 +490,8 @@ struct file_buffer { bool file_id_valid; FileID file_id; - char_u b_key[SIZEOF_INT * 2 + 1]; // key used for buf_hashtab, holds - // b_fnum as hex string - + char_u b_key[sizeof(handle_T) * 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. int b_changedtick; // incremented for each change, also for undo -- cgit From d204cbc0ceccbff32f454e62532f1a9a68f0b1ac Mon Sep 17 00:00:00 2001 From: rover Date: Wed, 4 Jan 2017 22:21:10 +0800 Subject: buffer.c: use a map instead of hashtab --- src/nvim/buffer.c | 30 ++++++++++++------------------ src/nvim/buffer_defs.h | 2 -- 2 files changed, 12 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 967c59ff8c..ad6fdc32c0 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -279,23 +279,24 @@ bool buf_valid(buf_T *buf) return false; } -/// A hash table used to quickly lookup a buffer by its number. -static hashtab_T buf_hashtab; +// Map used to quickly lookup a buffer by its number. +static PMap(handle_T) *buf_map = NULL; static void buf_hashtab_add(buf_T *buf) + FUNC_ATTR_NONNULL_ALL { - snprintf((char *)buf->b_key, sizeof(buf->b_key), "%x", buf->b_fnum); - if (hash_add(&buf_hashtab, buf->b_key) == FAIL) { + if (pmap_has(handle_T)(buf_map, buf->handle)) { EMSG(_("E931: Buffer cannot be registered")); + } else { + pmap_put(handle_T)(buf_map, buf->handle, buf); } } static void buf_hashtab_remove(buf_T *buf) + FUNC_ATTR_NONNULL_ALL { - hashitem_T *hi = hash_find(&buf_hashtab, buf->b_key); - - if (!HASHITEM_EMPTY(hi)) { - hash_remove(&buf_hashtab, hi); + if (pmap_has(handle_T)(buf_map, buf->handle)) { + pmap_del(handle_T)(buf_map, buf->handle); } } @@ -1386,7 +1387,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags) buf_T *buf; if (top_file_num == 1) { - hash_init(&buf_hashtab); + buf_map = pmap_new(handle_T)(); } fname_expand(curbuf, &ffname, &sfname); // will allocate ffname @@ -2025,19 +2026,12 @@ static char_u *fname_match(regmatch_T *rmp, char_u *name, bool ignore_case) /// Find a file in the buffer list by buffer number. buf_T *buflist_findnr(int nr) { - char_u key[sizeof(handle_T) * 2 + 1]; - hashitem_T *hi; - if (nr == 0) { nr = curwin->w_alt_fnum; } - snprintf((char *)key, sizeof(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))); + if (pmap_has(handle_T)(buf_map, (handle_T)nr)) { + return pmap_get(handle_T)(buf_map, (handle_T)nr); } return NULL; } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 353a2e0128..2b66a07f48 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -490,8 +490,6 @@ struct file_buffer { bool file_id_valid; FileID file_id; - char_u b_key[sizeof(handle_T) * 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. int b_changedtick; // incremented for each change, also for undo -- cgit