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.