diff options
author | Jussi Kivilinna <[email protected]> | 2018-11-08 19:31:12 +0000 |
---|---|---|
committer | Jussi Kivilinna <[email protected]> | 2018-11-08 19:31:12 +0000 |
commit | 2b5718c1f76851160115f455c3a9383b04521347 (patch) | |
tree | 47e8b954074c735aa5a690f4c705c97fba5c3c2e /common/iobuf.c | |
parent | g10/armor: remove unused unarmor_pump code (diff) | |
download | gnupg-2b5718c1f76851160115f455c3a9383b04521347.tar.gz gnupg-2b5718c1f76851160115f455c3a9383b04521347.zip |
common/iobuf: optimize iobuf_read_line
* common/iobuf.c (iobuf_read_line): Add fast path for finding '\n'
character in buffer.
--
This patch reduce per byte overhead in iobuf_read_line by avoiding
using iobuf_get when possible and use memchr to find '\n'. This
speeds armored decryption.
Benchmark results below, tested on Intel Core i7-4790K (turbo off).
Encrypted 2 GiB through pipe to ramfs file using AES128. Decrypt
ramfs file out through pipe to /dev/null.
before patch-set
----------------
gpg process
armor: user time pipe transfer rate
encrypt-aead: 13.8 140 MB/s
decrypt-aead: 30.6 68 MB/s
encrypt-cfb: 17.4 114 MB/s
decrypt-cfb: 32.6 64 MB/s
after (decrypt+iobuf opt)
-------------------------
gpg process
armor: user time pipe transfer rate
decrypt-aead: 22.5 92 MB/s
decrypt-cfb: 24.4 85 MB/s
Signed-off-by: Jussi Kivilinna <[email protected]>
Diffstat (limited to 'common/iobuf.c')
-rw-r--r-- | common/iobuf.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/common/iobuf.c b/common/iobuf.c index 18a458e0a..5eeba8fe6 100644 --- a/common/iobuf.c +++ b/common/iobuf.c @@ -2610,12 +2610,50 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer, } p = buffer; - while ((c = iobuf_get (a)) != -1) + while (1) { - *p++ = c; - nbytes++; - if (c == '\n') - break; + if (!a->nofast && a->d.start < a->d.len && nbytes < length - 1) + /* Fast path for finding '\n' by using standard C library's optimized + memchr. */ + { + unsigned size = a->d.len - a->d.start; + byte *newline_pos; + + if (size > length - 1 - nbytes) + size = length - 1 - nbytes; + + newline_pos = memchr (a->d.buf + a->d.start, '\n', size); + if (newline_pos) + { + /* Found newline, copy buffer and return. */ + size = (newline_pos - (a->d.buf + a->d.start)) + 1; + memcpy (p, a->d.buf + a->d.start, size); + p += size; + nbytes += size; + a->d.start += size; + a->nbytes += size; + break; + } + else + { + /* No newline, copy buffer and continue. */ + memcpy (p, a->d.buf + a->d.start, size); + p += size; + nbytes += size; + a->d.start += size; + a->nbytes += size; + } + } + else + { + c = iobuf_readbyte (a); + if (c == -1) + break; + *p++ = c; + nbytes++; + if (c == '\n') + break; + } if (nbytes == length - 1) /* We don't have enough space to add a \n and a \0. Increase |