mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.1666
Problem: When reading JSON from a channel all readahead is used. Solution: Use the fill function to reduce overhead.
This commit is contained in:
parent
8038568722
commit
46c00a6565
@ -1184,7 +1184,6 @@ write_buf_line(buf_T *buf, linenr_T lnum, channel_T *channel)
|
|||||||
int len = (int)STRLEN(line);
|
int len = (int)STRLEN(line);
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
|
||||||
/* TODO: check if channel can be written to, do not block on write */
|
|
||||||
if ((p = alloc(len + 2)) == NULL)
|
if ((p = alloc(len + 2)) == NULL)
|
||||||
return;
|
return;
|
||||||
STRCPY(p, line);
|
STRCPY(p, line);
|
||||||
@ -1213,13 +1212,14 @@ channel_write_in(channel_T *channel)
|
|||||||
in_part->ch_buffer = NULL;
|
in_part->ch_buffer = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (in_part->ch_fd == INVALID_FD)
|
|
||||||
/* pipe was closed */
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot
|
for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot
|
||||||
&& lnum <= buf->b_ml.ml_line_count; ++lnum)
|
&& lnum <= buf->b_ml.ml_line_count; ++lnum)
|
||||||
{
|
{
|
||||||
|
if (in_part->ch_fd == INVALID_FD)
|
||||||
|
/* pipe was closed */
|
||||||
|
return;
|
||||||
|
/* TODO: check if channel can be written to, do not block on write */
|
||||||
write_buf_line(buf, lnum, channel);
|
write_buf_line(buf, lnum, channel);
|
||||||
++written;
|
++written;
|
||||||
}
|
}
|
||||||
@ -1365,10 +1365,12 @@ channel_collapse(channel_T *channel, int part)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store "buf[len]" on "channel"/"part".
|
* Store "buf[len]" on "channel"/"part".
|
||||||
|
* When "prepend" is TRUE put in front, otherwise append at the end.
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead)
|
channel_save(channel_T *channel, int part, char_u *buf, int len,
|
||||||
|
int prepend, char *lead)
|
||||||
{
|
{
|
||||||
readq_T *node;
|
readq_T *node;
|
||||||
readq_T *head = &channel->ch_part[part].ch_head;
|
readq_T *head = &channel->ch_part[part].ch_head;
|
||||||
@ -1400,6 +1402,19 @@ channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead)
|
|||||||
node->rq_buffer[len] = NUL;
|
node->rq_buffer[len] = NUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prepend)
|
||||||
|
{
|
||||||
|
/* preend node to the head of the queue */
|
||||||
|
node->rq_next = head->rq_next;
|
||||||
|
node->rq_prev = NULL;
|
||||||
|
if (head->rq_next == NULL)
|
||||||
|
head->rq_prev = node;
|
||||||
|
else
|
||||||
|
head->rq_next->rq_prev = node;
|
||||||
|
head->rq_next = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* append node to the tail of the queue */
|
/* append node to the tail of the queue */
|
||||||
node->rq_next = NULL;
|
node->rq_next = NULL;
|
||||||
node->rq_prev = head->rq_prev;
|
node->rq_prev = head->rq_prev;
|
||||||
@ -1408,6 +1423,7 @@ channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead)
|
|||||||
else
|
else
|
||||||
head->rq_prev->rq_next = node;
|
head->rq_prev->rq_next = node;
|
||||||
head->rq_prev = node;
|
head->rq_prev = node;
|
||||||
|
}
|
||||||
|
|
||||||
if (log_fd != NULL && lead != NULL)
|
if (log_fd != NULL && lead != NULL)
|
||||||
{
|
{
|
||||||
@ -1420,6 +1436,42 @@ channel_save(channel_T *channel, int part, char_u *buf, int len, char *lead)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
channel_fill(js_read_T *reader)
|
||||||
|
{
|
||||||
|
channel_T *channel = (channel_T *)reader->js_cookie;
|
||||||
|
int part = reader->js_cookie_arg;
|
||||||
|
char_u *next = channel_get(channel, part);
|
||||||
|
int unused;
|
||||||
|
int len;
|
||||||
|
char_u *p;
|
||||||
|
|
||||||
|
if (next == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
unused = reader->js_end - reader->js_buf - reader->js_used;
|
||||||
|
if (unused > 0)
|
||||||
|
{
|
||||||
|
/* Prepend unused text. */
|
||||||
|
len = (int)STRLEN(next);
|
||||||
|
p = alloc(unused + len + 1);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
vim_free(next);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
mch_memmove(p, reader->js_buf + reader->js_used, unused);
|
||||||
|
mch_memmove(p + unused, next, len + 1);
|
||||||
|
vim_free(next);
|
||||||
|
next = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
vim_free(reader->js_buf);
|
||||||
|
reader->js_buf = next;
|
||||||
|
reader->js_used = 0;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use the read buffer of "channel"/"part" and parse a JSON message that is
|
* Use the read buffer of "channel"/"part" and parse a JSON message that is
|
||||||
* complete. The messages are added to the queue.
|
* complete. The messages are added to the queue.
|
||||||
@ -1439,13 +1491,11 @@ channel_parse_json(channel_T *channel, int part)
|
|||||||
if (channel_peek(channel, part) == NULL)
|
if (channel_peek(channel, part) == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* TODO: make reader work properly */
|
reader.js_buf = channel_get(channel, part);
|
||||||
/* reader.js_buf = channel_peek(channel, part); */
|
|
||||||
reader.js_buf = channel_get_all(channel, part);
|
|
||||||
reader.js_used = 0;
|
reader.js_used = 0;
|
||||||
reader.js_fill = NULL;
|
reader.js_fill = channel_fill;
|
||||||
/* reader.js_fill = channel_fill; */
|
|
||||||
reader.js_cookie = channel;
|
reader.js_cookie = channel;
|
||||||
|
reader.js_cookie_arg = part;
|
||||||
|
|
||||||
/* When a message is incomplete we wait for a short while for more to
|
/* When a message is incomplete we wait for a short while for more to
|
||||||
* arrive. After the delay drop the input, otherwise a truncated string
|
* arrive. After the delay drop the input, otherwise a truncated string
|
||||||
@ -1552,10 +1602,10 @@ channel_parse_json(channel_T *channel, int part)
|
|||||||
}
|
}
|
||||||
else if (reader.js_buf[reader.js_used] != NUL)
|
else if (reader.js_buf[reader.js_used] != NUL)
|
||||||
{
|
{
|
||||||
/* Put the unread part back into the channel.
|
/* Put the unread part back into the channel. */
|
||||||
* TODO: insert in front */
|
|
||||||
channel_save(channel, part, reader.js_buf + reader.js_used,
|
channel_save(channel, part, reader.js_buf + reader.js_used,
|
||||||
(int)(reader.js_end - reader.js_buf) - reader.js_used, NULL);
|
(int)(reader.js_end - reader.js_buf) - reader.js_used,
|
||||||
|
TRUE, NULL);
|
||||||
ret = status == MAYBE ? FALSE: TRUE;
|
ret = status == MAYBE ? FALSE: TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2419,7 +2469,7 @@ channel_read(channel_T *channel, int part, char *func)
|
|||||||
break; /* error or nothing more to read */
|
break; /* error or nothing more to read */
|
||||||
|
|
||||||
/* Store the read message in the queue. */
|
/* Store the read message in the queue. */
|
||||||
channel_save(channel, part, buf, len, "RECV ");
|
channel_save(channel, part, buf, len, FALSE, "RECV ");
|
||||||
readlen += len;
|
readlen += len;
|
||||||
if (len < MAXMSGSIZE)
|
if (len < MAXMSGSIZE)
|
||||||
break; /* did read everything that's available */
|
break; /* did read everything that's available */
|
||||||
@ -2446,7 +2496,7 @@ channel_read(channel_T *channel, int part, char *func)
|
|||||||
if (channel->ch_part[part].ch_mode == MODE_RAW
|
if (channel->ch_part[part].ch_mode == MODE_RAW
|
||||||
|| channel->ch_part[part].ch_mode == MODE_NL)
|
|| channel->ch_part[part].ch_mode == MODE_NL)
|
||||||
channel_save(channel, part, (char_u *)DETACH_MSG_RAW,
|
channel_save(channel, part, (char_u *)DETACH_MSG_RAW,
|
||||||
(int)STRLEN(DETACH_MSG_RAW), "PUT ");
|
(int)STRLEN(DETACH_MSG_RAW), FALSE, "PUT ");
|
||||||
|
|
||||||
/* TODO: When reading from stdout is not possible, should we try to
|
/* TODO: When reading from stdout is not possible, should we try to
|
||||||
* keep stdin and stderr open? Probably not, assume the other side
|
* keep stdin and stderr open? Probably not, assume the other side
|
||||||
|
@ -350,9 +350,11 @@ json_skip_white(js_read_T *reader)
|
|||||||
if (reader->js_fill != NULL && c == NUL)
|
if (reader->js_fill != NULL && c == NUL)
|
||||||
{
|
{
|
||||||
if (reader->js_fill(reader))
|
if (reader->js_fill(reader))
|
||||||
|
{
|
||||||
reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
|
reader->js_end = reader->js_buf + STRLEN(reader->js_buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (c == NUL || c > ' ')
|
if (c == NUL || c > ' ')
|
||||||
break;
|
break;
|
||||||
++reader->js_used;
|
++reader->js_used;
|
||||||
|
@ -2971,6 +2971,7 @@ struct js_reader
|
|||||||
/* function to fill the buffer or NULL;
|
/* function to fill the buffer or NULL;
|
||||||
* return TRUE when the buffer was filled */
|
* return TRUE when the buffer was filled */
|
||||||
void *js_cookie; /* can be used by js_fill */
|
void *js_cookie; /* can be used by js_fill */
|
||||||
|
int js_cookie_arg; /* can be used by js_fill */
|
||||||
};
|
};
|
||||||
typedef struct js_reader js_read_T;
|
typedef struct js_reader js_read_T;
|
||||||
|
|
||||||
|
@ -748,6 +748,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 */
|
||||||
|
/**/
|
||||||
|
1666,
|
||||||
/**/
|
/**/
|
||||||
1665,
|
1665,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user