forked from aniani/vim
patch 7.4.1891
Problem: Channel reading very long lines is slow. Solution: Collapse multiple buffers until a NL is found.
This commit is contained in:
@@ -1592,13 +1592,17 @@ channel_get_all(channel_T *channel, int part)
|
|||||||
|
|
||||||
/* Concatenate everything into one buffer. */
|
/* Concatenate everything into one buffer. */
|
||||||
for (node = head->rq_next; node != NULL; node = node->rq_next)
|
for (node = head->rq_next; node != NULL; node = node->rq_next)
|
||||||
len += (long_u)STRLEN(node->rq_buffer);
|
len += node->rq_buflen;
|
||||||
res = lalloc(len, TRUE);
|
res = lalloc(len, TRUE);
|
||||||
if (res == NULL)
|
if (res == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
*res = NUL;
|
p = res;
|
||||||
for (node = head->rq_next; node != NULL; node = node->rq_next)
|
for (node = head->rq_next; node != NULL; node = node->rq_next)
|
||||||
STRCAT(res, node->rq_buffer);
|
{
|
||||||
|
STRCPY(p, node->rq_buffer);
|
||||||
|
p += node->rq_buflen;
|
||||||
|
}
|
||||||
|
*p = NUL;
|
||||||
|
|
||||||
/* Free all buffers */
|
/* Free all buffers */
|
||||||
do
|
do
|
||||||
@@ -1613,31 +1617,59 @@ channel_get_all(channel_T *channel, int part)
|
|||||||
/*
|
/*
|
||||||
* Collapses the first and second buffer for "channel"/"part".
|
* Collapses the first and second buffer for "channel"/"part".
|
||||||
* Returns FAIL if that is not possible.
|
* Returns FAIL if that is not possible.
|
||||||
|
* When "want_nl" is TRUE collapse more buffers until a NL is found.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
channel_collapse(channel_T *channel, int part)
|
channel_collapse(channel_T *channel, int part, int want_nl)
|
||||||
{
|
{
|
||||||
readq_T *head = &channel->ch_part[part].ch_head;
|
readq_T *head = &channel->ch_part[part].ch_head;
|
||||||
readq_T *node = head->rq_next;
|
readq_T *node = head->rq_next;
|
||||||
|
readq_T *last_node;
|
||||||
|
readq_T *n;
|
||||||
|
char_u *newbuf;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
long_u len;
|
||||||
|
|
||||||
if (node == NULL || node->rq_next == NULL)
|
if (node == NULL || node->rq_next == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
p = alloc((unsigned)(STRLEN(node->rq_buffer)
|
last_node = node->rq_next;
|
||||||
+ STRLEN(node->rq_next->rq_buffer) + 1));
|
len = node->rq_buflen + last_node->rq_buflen + 1;
|
||||||
if (p == NULL)
|
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 */
|
return FAIL; /* out of memory */
|
||||||
STRCPY(p, node->rq_buffer);
|
STRCPY(p, node->rq_buffer);
|
||||||
STRCAT(p, node->rq_next->rq_buffer);
|
p += node->rq_buflen;
|
||||||
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->rq_buffer);
|
||||||
vim_free(node);
|
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;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1673,11 +1705,13 @@ channel_save(channel_T *channel, int part, char_u *buf, int len,
|
|||||||
if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL)
|
if (buf[i] != CAR || i + 1 >= len || buf[i + 1] != NL)
|
||||||
*p++ = buf[i];
|
*p++ = buf[i];
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
|
node->rq_buflen = (long_u)(p - node->rq_buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mch_memmove(node->rq_buffer, buf, len);
|
mch_memmove(node->rq_buffer, buf, len);
|
||||||
node->rq_buffer[len] = NUL;
|
node->rq_buffer[len] = NUL;
|
||||||
|
node->rq_buflen = (long_u)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prepend)
|
if (prepend)
|
||||||
@@ -2024,7 +2058,7 @@ channel_exe_cmd(channel_T *channel, int part, typval_T *argv)
|
|||||||
#ifdef FEAT_GUI
|
#ifdef FEAT_GUI
|
||||||
if (gui.in_use)
|
if (gui.in_use)
|
||||||
{
|
{
|
||||||
gui_update_cursor(FALSE, FALSE);
|
gui_update_cursor(TRUE, FALSE);
|
||||||
gui_mch_flush();
|
gui_mch_flush();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2349,7 +2383,7 @@ may_invoke_callback(channel_T *channel, int part)
|
|||||||
nl = vim_strchr(buf, NL);
|
nl = vim_strchr(buf, NL);
|
||||||
if (nl != NULL)
|
if (nl != NULL)
|
||||||
break;
|
break;
|
||||||
if (channel_collapse(channel, part) == FAIL)
|
if (channel_collapse(channel, part, TRUE) == FAIL)
|
||||||
return FALSE; /* incomplete message */
|
return FALSE; /* incomplete message */
|
||||||
}
|
}
|
||||||
if (nl[1] == NUL)
|
if (nl[1] == NUL)
|
||||||
@@ -3018,7 +3052,8 @@ channel_read_block(channel_T *channel, int part, int timeout)
|
|||||||
if (buf != NULL && (mode == MODE_RAW
|
if (buf != NULL && (mode == MODE_RAW
|
||||||
|| (mode == MODE_NL && vim_strchr(buf, NL) != NULL)))
|
|| (mode == MODE_NL && vim_strchr(buf, NL) != NULL)))
|
||||||
break;
|
break;
|
||||||
if (buf != NULL && channel_collapse(channel, part) == OK)
|
if (buf != NULL && channel_collapse(channel, part, mode == MODE_NL)
|
||||||
|
== OK)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Wait for up to the channel timeout. */
|
/* Wait for up to the channel timeout. */
|
||||||
|
@@ -399,7 +399,7 @@ netbeans_parse_messages(void)
|
|||||||
/* Command isn't complete. If there is no following buffer,
|
/* Command isn't complete. If there is no following buffer,
|
||||||
* return (wait for more). If there is another buffer following,
|
* return (wait for more). If there is another buffer following,
|
||||||
* prepend the text to that buffer and delete this one. */
|
* prepend the text to that buffer and delete this one. */
|
||||||
if (channel_collapse(nb_channel, PART_SOCK) == FAIL)
|
if (channel_collapse(nb_channel, PART_SOCK, TRUE) == FAIL)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -18,7 +18,7 @@ void channel_buffer_free(buf_T *buf);
|
|||||||
void channel_write_any_lines(void);
|
void channel_write_any_lines(void);
|
||||||
void channel_write_new_lines(buf_T *buf);
|
void channel_write_new_lines(buf_T *buf);
|
||||||
char_u *channel_get(channel_T *channel, int part);
|
char_u *channel_get(channel_T *channel, int part);
|
||||||
int channel_collapse(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_can_write_to(channel_T *channel);
|
||||||
int channel_is_open(channel_T *channel);
|
int channel_is_open(channel_T *channel);
|
||||||
char *channel_status(channel_T *channel);
|
char *channel_status(channel_T *channel);
|
||||||
|
@@ -1309,6 +1309,7 @@ struct jobvar_S
|
|||||||
struct readq_S
|
struct readq_S
|
||||||
{
|
{
|
||||||
char_u *rq_buffer;
|
char_u *rq_buffer;
|
||||||
|
long_u rq_buflen;
|
||||||
readq_T *rq_next;
|
readq_T *rq_next;
|
||||||
readq_T *rq_prev;
|
readq_T *rq_prev;
|
||||||
};
|
};
|
||||||
|
@@ -753,6 +753,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1891,
|
||||||
/**/
|
/**/
|
||||||
1890,
|
1890,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user