Skip to content

Commit

Permalink
vtysh: optimize printout routine
Browse files Browse the repository at this point in the history
When printing responses from a client, vtysh searches through every
response it receives twice. Once is to look for the terminating
sequence and the other is to translate \n to \0, which is used with the
line processing callback capability. However:

* There's no need to search all of the output for the terminator, we can
  just check the last 4 bytes.
* In most scenarios we won't have a callback. Therefore we don't need to
  process the output and can just dump it.

Together these optimizations have a significant impact on the total
runtime of talkative CLI commands, such as `sh ip bgp json` which runs
roughly 1000% faster when dumping 1,000,000 routes.

Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
  • Loading branch information
qlyoung committed Jan 8, 2018
1 parent 4060fcc commit 08ee8e2
Showing 1 changed file with 23 additions and 7 deletions.
30 changes: 23 additions & 7 deletions vtysh/vtysh.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,25 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,

bufvalid += nread;

end = memmem(buf, bufvalid - buf, terminator,
sizeof(terminator));
if (end + sizeof(terminator) + 1 > bufvalid)
if (bufvalid - buf >= 4)
end = memmem(bufvalid - 4, 4, terminator,
sizeof(terminator));

if (end && end + sizeof(terminator) + 1 > bufvalid)
/* found \0\0\0 but return code hasn't been read yet */
end = NULL;
if (end)
ret = end[sizeof(terminator)];

while (bufvalid > buf && (end > buf || !end)) {
size_t textlen = (end ? end : bufvalid) - buf;
/*
* calculate # bytes we have, up to & not including the
* terminator if present
*/
size_t textlen = (end ? end : bufvalid) - buf;

/* feed line processing callback if present */
while (callback && bufvalid > buf && (end > buf || !end)) {
textlen = (end ? end : bufvalid) - buf;
char *eol = memchr(buf, '\n', textlen);
if (eol)
/* line break */
Expand All @@ -165,8 +174,7 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
/* continue reading */
break;

/* eol is at a line end now, either \n => \0 or \0\0\0
*/
/* eol is at line end now, either \n => \0 or \0\0\0 */
assert(eol && eol <= bufvalid);

if (fp) {
Expand All @@ -186,6 +194,14 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
end -= eol - buf;
}

/* else if no callback, dump raw */
if (!callback) {
if (fp)
fwrite(buf, 1, textlen, fp);
memmove(buf, buf + textlen, bufvalid - buf - textlen);
bufvalid -= textlen;
}

if (bufvalid == buf + bufsz) {
char *new;
bufsz *= 2;
Expand Down

0 comments on commit 08ee8e2

Please sign in to comment.