Mailing List Archive

[PATCH 5/8] 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 <jussi.kivilinna@iki.fi>
---
0 files changed

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


_______________________________________________
Gnupg-devel mailing list
Gnupg-devel@gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-devel