Mercurial > vim
comparison src/buffer.c @ 9511:c2e904cc064f v7.4.2036
commit https://github.com/vim/vim/commit/480778b805bd8bdc5d657560230e9c50feda1d0f
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Jul 14 22:09:39 2016 +0200
patch 7.4.2036
Problem: Looking up a buffer by number is slow if there are many.
Solution: Use a hashtab.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 14 Jul 2016 22:15:06 +0200 |
parents | 69ed2c9d34a6 |
children | bb538c090668 |
comparison
equal
deleted
inserted
replaced
9510:e0f0aa1e3571 | 9511:c2e904cc064f |
---|---|
345 * one. */ | 345 * one. */ |
346 for (bp = lastbuf; bp != NULL; bp = bp->b_prev) | 346 for (bp = lastbuf; bp != NULL; bp = bp->b_prev) |
347 if (bp == buf) | 347 if (bp == buf) |
348 return TRUE; | 348 return TRUE; |
349 return FALSE; | 349 return FALSE; |
350 } | |
351 | |
352 /* | |
353 * A hash table used to quickly lookup a buffer by its number. | |
354 */ | |
355 static hashtab_T buf_hashtab; | |
356 | |
357 static void | |
358 buf_hashtab_add(buf_T *buf) | |
359 { | |
360 sprintf((char *)buf->b_key, "%x", buf->b_fnum); | |
361 if (hash_add(&buf_hashtab, buf->b_key) == FAIL) | |
362 EMSG(_("E931: Buffer cannot be registered")); | |
363 } | |
364 | |
365 static void | |
366 buf_hashtab_remove(buf_T *buf) | |
367 { | |
368 hashitem_T *hi = hash_find(&buf_hashtab, buf->b_key); | |
369 | |
370 if (!HASHITEM_EMPTY(hi)) | |
371 hash_remove(&buf_hashtab, hi); | |
350 } | 372 } |
351 | 373 |
352 /* | 374 /* |
353 * Close the link to a buffer. | 375 * Close the link to a buffer. |
354 * "action" is used when there is no longer a window for the buffer. | 376 * "action" is used when there is no longer a window for the buffer. |
721 #ifdef FEAT_JOB_CHANNEL | 743 #ifdef FEAT_JOB_CHANNEL |
722 channel_buffer_free(buf); | 744 channel_buffer_free(buf); |
723 #endif | 745 #endif |
724 #ifdef FEAT_AUTOCMD | 746 #ifdef FEAT_AUTOCMD |
725 aubuflocal_remove(buf); | 747 aubuflocal_remove(buf); |
748 | |
749 buf_hashtab_remove(buf); | |
750 | |
726 if (autocmd_busy) | 751 if (autocmd_busy) |
727 { | 752 { |
728 /* Do not free the buffer structure while autocommands are executing, | 753 /* Do not free the buffer structure while autocommands are executing, |
729 * it's still needed. Free it when autocmd_busy is reset. */ | 754 * it's still needed. Free it when autocmd_busy is reset. */ |
730 buf->b_next = au_pending_free_buf; | 755 buf->b_next = au_pending_free_buf; |
1701 | 1726 |
1702 /* | 1727 /* |
1703 * functions for dealing with the buffer list | 1728 * functions for dealing with the buffer list |
1704 */ | 1729 */ |
1705 | 1730 |
1731 static int top_file_num = 1; /* highest file number */ | |
1732 | |
1706 /* | 1733 /* |
1707 * Add a file name to the buffer list. Return a pointer to the buffer. | 1734 * Add a file name to the buffer list. Return a pointer to the buffer. |
1708 * If the same file name already exists return a pointer to that buffer. | 1735 * If the same file name already exists return a pointer to that buffer. |
1709 * If it does not exist, or if fname == NULL, a new entry is created. | 1736 * If it does not exist, or if fname == NULL, a new entry is created. |
1710 * If (flags & BLN_CURBUF) is TRUE, may use current buffer. | 1737 * If (flags & BLN_CURBUF) is TRUE, may use current buffer. |
1713 * If (flags & BLN_NEW) is TRUE, don't use an existing buffer. | 1740 * If (flags & BLN_NEW) is TRUE, don't use an existing buffer. |
1714 * If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer | 1741 * If (flags & BLN_NOOPT) is TRUE, don't copy options from the current buffer |
1715 * if the buffer already exists. | 1742 * if the buffer already exists. |
1716 * This is the ONLY way to create a new buffer. | 1743 * This is the ONLY way to create a new buffer. |
1717 */ | 1744 */ |
1718 static int top_file_num = 1; /* highest file number */ | |
1719 | |
1720 buf_T * | 1745 buf_T * |
1721 buflist_new( | 1746 buflist_new( |
1722 char_u *ffname, /* full path of fname or relative */ | 1747 char_u *ffname, /* full path of fname or relative */ |
1723 char_u *sfname, /* short fname or NULL */ | 1748 char_u *sfname, /* short fname or NULL */ |
1724 linenr_T lnum, /* preferred cursor line */ | 1749 linenr_T lnum, /* preferred cursor line */ |
1726 { | 1751 { |
1727 buf_T *buf; | 1752 buf_T *buf; |
1728 #ifdef UNIX | 1753 #ifdef UNIX |
1729 stat_T st; | 1754 stat_T st; |
1730 #endif | 1755 #endif |
1756 | |
1757 if (top_file_num == 1) | |
1758 hash_init(&buf_hashtab); | |
1731 | 1759 |
1732 fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ | 1760 fname_expand(curbuf, &ffname, &sfname); /* will allocate ffname */ |
1733 | 1761 |
1734 /* | 1762 /* |
1735 * If file name already exists in the list, update the entry. | 1763 * If file name already exists in the list, update the entry. |
1905 out_flush(); | 1933 out_flush(); |
1906 ui_delay(3000L, TRUE); /* make sure it is noticed */ | 1934 ui_delay(3000L, TRUE); /* make sure it is noticed */ |
1907 } | 1935 } |
1908 top_file_num = 1; | 1936 top_file_num = 1; |
1909 } | 1937 } |
1938 buf_hashtab_add(buf); | |
1910 | 1939 |
1911 /* | 1940 /* |
1912 * Always copy the options from the current buffer. | 1941 * Always copy the options from the current buffer. |
1913 */ | 1942 */ |
1914 buf_copy_options(buf, BCO_ALWAYS); | 1943 buf_copy_options(buf, BCO_ALWAYS); |
2577 return match; | 2606 return match; |
2578 } | 2607 } |
2579 #endif | 2608 #endif |
2580 | 2609 |
2581 /* | 2610 /* |
2582 * find file in buffer list by number | 2611 * Find a file in the buffer list by buffer number. |
2583 */ | 2612 */ |
2584 buf_T * | 2613 buf_T * |
2585 buflist_findnr(int nr) | 2614 buflist_findnr(int nr) |
2586 { | 2615 { |
2587 buf_T *buf; | 2616 char_u key[VIM_SIZEOF_INT * 2 + 1]; |
2617 hashitem_T *hi; | |
2588 | 2618 |
2589 if (nr == 0) | 2619 if (nr == 0) |
2590 nr = curwin->w_alt_fnum; | 2620 nr = curwin->w_alt_fnum; |
2591 /* Assume newer buffers are used more often, start from the end. */ | 2621 sprintf((char *)key, "%x", nr); |
2592 for (buf = lastbuf; buf != NULL; buf = buf->b_prev) | 2622 hi = hash_find(&buf_hashtab, key); |
2593 if (buf->b_fnum == nr) | 2623 |
2594 return buf; | 2624 if (!HASHITEM_EMPTY(hi)) |
2625 return (buf_T *)(hi->hi_key | |
2626 - ((unsigned)(curbuf->b_key - (char_u *)curbuf))); | |
2595 return NULL; | 2627 return NULL; |
2596 } | 2628 } |
2597 | 2629 |
2598 /* | 2630 /* |
2599 * Get name of file 'n' in the buffer list. | 2631 * Get name of file 'n' in the buffer list. |