To: vim_dev@googlegroups.com Subject: Patch 7.4.1891 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 7.4.1891 Problem: Channel reading very long lines is slow. Solution: Collapse multiple buffers until a NL is found. Files: src/channel.c, src/netbeans.c, src/proto/channel.pro, src/structs.h *** ../vim-7.4.1890/src/channel.c 2016-06-02 20:05:22.480384217 +0200 --- src/channel.c 2016-06-04 17:14:10.898148509 +0200 *************** *** 1592,1604 **** /* Concatenate everything into one buffer. */ for (node = head->rq_next; node != NULL; node = node->rq_next) ! len += (long_u)STRLEN(node->rq_buffer); res = lalloc(len, TRUE); if (res == NULL) return NULL; ! *res = NUL; for (node = head->rq_next; node != NULL; node = node->rq_next) ! STRCAT(res, node->rq_buffer); /* Free all buffers */ do --- 1592,1608 ---- /* Concatenate everything into one buffer. */ for (node = head->rq_next; node != NULL; node = node->rq_next) ! len += node->rq_buflen; res = lalloc(len, TRUE); if (res == NULL) return NULL; ! p = res; for (node = head->rq_next; node != NULL; node = node->rq_next) ! { ! STRCPY(p, node->rq_buffer); ! p += node->rq_buflen; ! } ! *p = NUL; /* Free all buffers */ do *************** *** 1613,1643 **** /* * Collapses the first and second buffer for "channel"/"part". * Returns FAIL if that is not possible. */ int ! channel_collapse(channel_T *channel, int part) { readq_T *head = &channel->ch_part[part].ch_head; readq_T *node = head->rq_next; char_u *p; if (node == NULL || node->rq_next == NULL) return FAIL; ! p = alloc((unsigned)(STRLEN(node->rq_buffer) ! + STRLEN(node->rq_next->rq_buffer) + 1)); ! if (p == NULL) return FAIL; /* out of memory */ STRCPY(p, node->rq_buffer); ! STRCAT(p, node->rq_next->rq_buffer); ! vim_free(node->rq_next->rq_buffer); ! node->rq_next->rq_buffer = p; ! ! /* dispose of the node and its buffer */ ! head->rq_next = node->rq_next; ! head->rq_next->rq_prev = NULL; vim_free(node->rq_buffer); ! vim_free(node); return OK; } --- 1617,1675 ---- /* * Collapses the first and second buffer for "channel"/"part". * Returns FAIL if that is not possible. + * When "want_nl" is TRUE collapse more buffers until a NL is found. */ int ! channel_collapse(channel_T *channel, int part, int want_nl) { readq_T *head = &channel->ch_part[part].ch_head; readq_T *node = head->rq_next; + readq_T *last_node; + readq_T *n; + char_u *newbuf; char_u *p; + long_u len; if (node == NULL || node->rq_next == NULL) return FAIL; ! last_node = node->rq_next; ! len = node->rq_buflen + last_node->rq_buflen + 1; ! if (want_nl) ! while (last_node->rq_next != NULL ! && vim_strchr(last_node->rq_buffer, NL) == NULL) ! { ! last_node = last_node->rq_next; ! len += last_node->rq_buflen; ! } ! ! p = newbuf = alloc(len); ! if (newbuf == NULL) return FAIL; /* out of memory */ STRCPY(p, node->rq_buffer); ! p += node->rq_buflen; vim_free(node->rq_buffer); ! node->rq_buffer = newbuf; ! for (n = node; n != last_node; ) ! { ! n = n->rq_next; ! STRCPY(p, n->rq_buffer); ! p += n->rq_buflen; ! vim_free(n->rq_buffer); ! } ! ! /* dispose of the collapsed nodes and their buffers */ ! for (n = node->rq_next; n != last_node; ) ! { ! n = n->rq_next; ! vim_free(n->rq_prev); ! } ! node->rq_next = last_node->rq_next; ! if (last_node->rq_next == NULL) ! head->rq_prev = node; ! else ! last_node->rq_next->rq_prev = node; ! vim_free(last_node); return OK; } *************** *** 1673,1683 **** --- 1705,1717 ---- if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL) *p++ = buf[i]; *p = NUL; + node->rq_buflen = (long_u)(p - node->rq_buffer); } else { mch_memmove(node->rq_buffer, buf, len); node->rq_buffer[len] = NUL; + node->rq_buflen = (long_u)len; } if (prepend) *************** *** 2024,2030 **** #ifdef FEAT_GUI if (gui.in_use) { ! gui_update_cursor(FALSE, FALSE); gui_mch_flush(); } #endif --- 2058,2064 ---- #ifdef FEAT_GUI if (gui.in_use) { ! gui_update_cursor(TRUE, FALSE); gui_mch_flush(); } #endif *************** *** 2349,2355 **** nl = vim_strchr(buf, NL); if (nl != NULL) break; ! if (channel_collapse(channel, part) == FAIL) return FALSE; /* incomplete message */ } if (nl[1] == NUL) --- 2383,2389 ---- nl = vim_strchr(buf, NL); if (nl != NULL) break; ! if (channel_collapse(channel, part, TRUE) == FAIL) return FALSE; /* incomplete message */ } if (nl[1] == NUL) *************** *** 3018,3024 **** if (buf != NULL && (mode == MODE_RAW || (mode == MODE_NL && vim_strchr(buf, NL) != NULL))) break; ! if (buf != NULL && channel_collapse(channel, part) == OK) continue; /* Wait for up to the channel timeout. */ --- 3052,3059 ---- if (buf != NULL && (mode == MODE_RAW || (mode == MODE_NL && vim_strchr(buf, NL) != NULL))) break; ! if (buf != NULL && channel_collapse(channel, part, mode == MODE_NL) ! == OK) continue; /* Wait for up to the channel timeout. */ *** ../vim-7.4.1890/src/netbeans.c 2016-04-30 18:06:47.114331342 +0200 --- src/netbeans.c 2016-06-04 16:57:10.998162539 +0200 *************** *** 399,405 **** /* Command isn't complete. If there is no following buffer, * return (wait for more). If there is another buffer following, * prepend the text to that buffer and delete this one. */ ! if (channel_collapse(nb_channel, PART_SOCK) == FAIL) return; } else --- 399,405 ---- /* Command isn't complete. If there is no following buffer, * return (wait for more). If there is another buffer following, * prepend the text to that buffer and delete this one. */ ! if (channel_collapse(nb_channel, PART_SOCK, TRUE) == FAIL) return; } else *** ../vim-7.4.1890/src/proto/channel.pro 2016-06-02 20:05:22.480384217 +0200 --- src/proto/channel.pro 2016-06-04 16:58:02.154161835 +0200 *************** *** 18,24 **** void channel_write_any_lines(void); void channel_write_new_lines(buf_T *buf); char_u *channel_get(channel_T *channel, int part); ! int channel_collapse(channel_T *channel, int part); int channel_can_write_to(channel_T *channel); int channel_is_open(channel_T *channel); char *channel_status(channel_T *channel); --- 18,24 ---- void channel_write_any_lines(void); void channel_write_new_lines(buf_T *buf); char_u *channel_get(channel_T *channel, int part); ! int channel_collapse(channel_T *channel, int part, int want_nl); int channel_can_write_to(channel_T *channel); int channel_is_open(channel_T *channel); char *channel_status(channel_T *channel); *** ../vim-7.4.1890/src/structs.h 2016-06-03 19:05:37.287245034 +0200 --- src/structs.h 2016-06-04 17:05:51.546155378 +0200 *************** *** 1309,1314 **** --- 1309,1315 ---- struct readq_S { char_u *rq_buffer; + long_u rq_buflen; readq_T *rq_next; readq_T *rq_prev; }; *** ../vim-7.4.1890/src/version.c 2016-06-04 16:24:28.918189529 +0200 --- src/version.c 2016-06-04 17:15:34.778147355 +0200 *************** *** 755,756 **** --- 755,758 ---- { /* Add new patch number below this line */ + /**/ + 1891, /**/ -- "Oh, no! NOT the Spanish Inquisition!" "NOBODY expects the Spanish Inquisition!!!" -- Monty Python sketch -- "Oh, no! NOT another option!" "EVERYBODY expects another option!!!" -- Discussion in vim-dev mailing list -- /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///