To: vim_dev@googlegroups.com Subject: Patch 9.0.0749 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0749 Problem: Alloc/free of buffer for each quickfix entry is inefficient. Solution: Use a shared grow array. (Yegappan Lakshmanan, closes #11365) Files: src/alloc.c, src/quickfix.c, src/proto/quickfix.pro *** ../vim-9.0.0748/src/alloc.c 2022-09-05 14:33:42.202419990 +0100 --- src/alloc.c 2022-10-14 13:09:20.617240991 +0100 *************** *** 472,486 **** # endif # ifdef FEAT_QUICKFIX ! { ! win_T *win; ! tabpage_T *tab; ! ! qf_free_all(NULL); ! // Free all location lists ! FOR_ALL_TAB_WINDOWS(tab, win) ! qf_free_all(win); ! } # endif // Close all script inputs. --- 472,478 ---- # endif # ifdef FEAT_QUICKFIX ! free_quickfix(); # endif // Close all script inputs. *** ../vim-9.0.0748/src/quickfix.c 2022-10-13 11:59:18.845930012 +0100 --- src/quickfix.c 2022-10-14 13:10:39.168938276 +0100 *************** *** 219,224 **** --- 219,247 ---- static char_u *qf_last_bufname = NULL; static bufref_T qf_last_bufref = {NULL, 0, 0}; + static garray_T qfga; + + /* + * Get a growarray to buffer text in. Shared between various commands to avoid + * many alloc/free calls. + */ + static garray_T * + qfga_get(void) + { + static int initialized = FALSE; + + if (!initialized) + { + initialized = TRUE; + ga_init2(&qfga, 1, 256); + } + + // Retain ga_data from previous use. Reset the length to zero. + qfga.ga_len = 0; + + return &qfga; + } + /* * Maximum number of bytes allowed per line while reading a errorfile. */ *************** *** 3286,3292 **** linenr_T old_lnum) { linenr_T i; ! garray_T ga; // Update the screen before showing the message, unless the screen // scrolled up. --- 3309,3317 ---- linenr_T old_lnum) { linenr_T i; ! garray_T *gap; ! ! gap = qfga_get(); // Update the screen before showing the message, unless the screen // scrolled up. *************** *** 3297,3305 **** qf_ptr->qf_cleared ? _(" (line deleted)") : "", (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); // Add the message, skipping leading whitespace and newlines. ! ga_init2(&ga, 1, 256); ! ga_concat(&ga, IObuff); ! qf_fmt_text(&ga, skipwhite(qf_ptr->qf_text)); // Output the message. Overwrite to avoid scrolling when the 'O' // flag is present in 'shortmess'; But when not jumping, print the --- 3322,3329 ---- qf_ptr->qf_cleared ? _(" (line deleted)") : "", (char *)qf_types(qf_ptr->qf_type, qf_ptr->qf_nr)); // Add the message, skipping leading whitespace and newlines. ! ga_concat(gap, IObuff); ! qf_fmt_text(gap, skipwhite(qf_ptr->qf_text)); // Output the message. Overwrite to avoid scrolling when the 'O' // flag is present in 'shortmess'; But when not jumping, print the *************** *** 3309,3317 **** msg_scroll = TRUE; else if (!msg_scrolled && shortmess(SHM_OVERALL)) msg_scroll = FALSE; ! msg_attr_keep((char *)ga.ga_data, 0, TRUE); msg_scroll = i; - ga_clear(&ga); } /* --- 3333,3340 ---- msg_scroll = TRUE; else if (!msg_scrolled && shortmess(SHM_OVERALL)) msg_scroll = FALSE; ! msg_attr_keep((char *)gap->ga_data, 0, TRUE); msg_scroll = i; } /* *************** *** 3576,3582 **** char_u *fname; buf_T *buf; int filter_entry; ! garray_T ga; fname = NULL; if (qfp->qf_module != NULL && *qfp->qf_module != NUL) --- 3599,3605 ---- char_u *fname; buf_T *buf; int filter_entry; ! garray_T *gap; fname = NULL; if (qfp->qf_module != NULL && *qfp->qf_module != NUL) *************** *** 3617,3650 **** if (qfp->qf_lnum != 0) msg_puts_attr(":", qfSepAttr); ! ga_init2(&ga, 1, 256); if (qfp->qf_lnum == 0) ! ga_append(&ga, NUL); else ! qf_range_text(&ga, qfp); ! ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); ! ga_append(&ga, NUL); ! msg_puts_attr((char *)ga.ga_data, qfLineAttr); ! ga_clear(&ga); msg_puts_attr(":", qfSepAttr); if (qfp->qf_pattern != NULL) { ! qf_fmt_text(&ga, qfp->qf_pattern); ! msg_puts((char *)ga.ga_data); ! ga_clear(&ga); msg_puts_attr(":", qfSepAttr); } msg_puts(" "); ! { ! // Remove newlines and leading whitespace from the text. For an ! // unrecognized line keep the indent, the compiler may mark a word ! // with ^^^^. ! qf_fmt_text(&ga, (fname != NULL || qfp->qf_lnum != 0) ! ? skipwhite(qfp->qf_text) : qfp->qf_text); ! msg_prt_line((char_u *)ga.ga_data, FALSE); ! ga_clear(&ga); ! } out_flush(); // show one line at a time } --- 3640,3670 ---- if (qfp->qf_lnum != 0) msg_puts_attr(":", qfSepAttr); ! gap = qfga_get(); if (qfp->qf_lnum == 0) ! ga_append(gap, NUL); else ! qf_range_text(gap, qfp); ! ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr)); ! ga_append(gap, NUL); ! msg_puts_attr((char *)gap->ga_data, qfLineAttr); msg_puts_attr(":", qfSepAttr); if (qfp->qf_pattern != NULL) { ! gap = qfga_get(); ! qf_fmt_text(gap, qfp->qf_pattern); ! msg_puts((char *)gap->ga_data); msg_puts_attr(":", qfSepAttr); } msg_puts(" "); ! // Remove newlines and leading whitespace from the text. For an ! // unrecognized line keep the indent, the compiler may mark a word ! // with ^^^^. ! gap = qfga_get(); ! qf_fmt_text(gap, (fname != NULL || qfp->qf_lnum != 0) ! ? skipwhite(qfp->qf_text) : qfp->qf_text); ! msg_prt_line((char_u *)gap->ga_data, FALSE); out_flush(); // show one line at a time } *************** *** 4593,4616 **** char_u *qftf_str) { buf_T *errbuf; ! garray_T ga; ! ga_init2(&ga, 1, 256); // If the 'quickfixtextfunc' function returned a non-empty custom string // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) ! ga_concat(&ga, qftf_str); else { if (qfp->qf_module != NULL) ! ga_concat(&ga, qfp->qf_module); else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { if (qfp->qf_type == 1) // :helpgrep ! ga_concat(&ga, gettail(errbuf->b_fname)); else { // Shorten the file name if not done already. --- 4613,4636 ---- char_u *qftf_str) { buf_T *errbuf; ! garray_T *gap; ! gap = qfga_get(); // If the 'quickfixtextfunc' function returned a non-empty custom string // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) ! ga_concat(gap, qftf_str); else { if (qfp->qf_module != NULL) ! ga_concat(gap, qfp->qf_module); else if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { if (qfp->qf_type == 1) // :helpgrep ! ga_concat(gap, gettail(errbuf->b_fname)); else { // Shorten the file name if not done already. *************** *** 4623,4657 **** mch_dirname(dirname, MAXPATHL); shorten_buf_fname(errbuf, dirname, FALSE); } ! ga_concat(&ga, errbuf->b_fname); } } ! ga_append(&ga, '|'); if (qfp->qf_lnum > 0) { ! qf_range_text(&ga, qfp); ! ga_concat(&ga, qf_types(qfp->qf_type, qfp->qf_nr)); } else if (qfp->qf_pattern != NULL) ! qf_fmt_text(&ga, qfp->qf_pattern); ! ga_append(&ga, '|'); ! ga_append(&ga, ' '); // Remove newlines and leading whitespace from the text. // For an unrecognized line keep the indent, the compiler may // mark a word with ^^^^. ! qf_fmt_text(&ga, ga.ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); } ! ga_append(&ga, NUL); ! if (ml_append_buf(buf, lnum, ga.ga_data, ga.ga_len + 1, FALSE) == FAIL) return FAIL; - ga_clear(&ga); - return OK; } --- 4643,4675 ---- mch_dirname(dirname, MAXPATHL); shorten_buf_fname(errbuf, dirname, FALSE); } ! ga_concat(gap, errbuf->b_fname); } } ! ga_append(gap, '|'); if (qfp->qf_lnum > 0) { ! qf_range_text(gap, qfp); ! ga_concat(gap, qf_types(qfp->qf_type, qfp->qf_nr)); } else if (qfp->qf_pattern != NULL) ! qf_fmt_text(gap, qfp->qf_pattern); ! ga_append(gap, '|'); ! ga_append(gap, ' '); // Remove newlines and leading whitespace from the text. // For an unrecognized line keep the indent, the compiler may // mark a word with ^^^^. ! qf_fmt_text(gap, gap->ga_len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text); } ! ga_append(gap, NUL); ! if (ml_append_buf(buf, lnum, gap->ga_data, gap->ga_len + 1, FALSE) == FAIL) return FAIL; return OK; } *************** *** 8376,8381 **** --- 8394,8416 ---- curwin->w_llist = qi; } } + + # if defined(EXITFREE) || defined(PROTO) + void + free_quickfix() + { + win_T *win; + tabpage_T *tab; + + qf_free_all(NULL); + // Free all location lists + FOR_ALL_TAB_WINDOWS(tab, win) + qf_free_all(win); + + ga_clear(&qfga); + } + # endif + #endif // FEAT_QUICKFIX #if defined(FEAT_EVAL) || defined(PROTO) *** ../vim-9.0.0748/src/proto/quickfix.pro 2022-06-27 23:15:20.000000000 +0100 --- src/proto/quickfix.pro 2022-10-14 13:09:15.717261161 +0100 *************** *** 35,40 **** --- 35,41 ---- int cexpr_core(exarg_T *eap, typval_T *tv); void ex_cexpr(exarg_T *eap); void ex_helpgrep(exarg_T *eap); + void free_quickfix(void); void f_getloclist(typval_T *argvars, typval_T *rettv); void f_getqflist(typval_T *argvars, typval_T *rettv); void f_setloclist(typval_T *argvars, typval_T *rettv); *** ../vim-9.0.0748/src/version.c 2022-10-14 12:08:19.316833076 +0100 --- src/version.c 2022-10-14 13:07:37.993698958 +0100 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 749, /**/ -- TIM: But follow only if you are men of valour. For the entrance to this cave is guarded by a monster, a creature so foul and cruel that no man yet has fought with it and lived. Bones of full fifty men lie strewn about its lair ... "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///