Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Sat, 24 Oct 2015 18:15:58 UTC Commit: cbc85b7444da9e5210f1a7ac18a1e223af784af9 https://github.com/geany/geany/commit/cbc85b7444da9e5210f1a7ac18a1e223af784a...
Log Message: ----------- Improve memory backend of mio_read()
Drop the loop in mem_read() in favor of a single memcpy() call.
This greatly improves performances when nmemb > 1, for a small loss for some values of size when nmemb == 1. Gain can theoretically be infinite since swapping nmemb and size parameters changes almost nothing while it had a dramatic performance impact previously. Loss is up to about 25% in the worst case for some values of size when nmemb is 1.
Also, now the function always copies as much data as possible, not only whole blocks. This follows the glibc implementation of fread() and simplifies the code. Doing so also fixes the position after a partial read to be at the last readable character rather than the end of the last read block.
Modified Paths: -------------- tagmanager/mio/mio-memory.c
Modified: tagmanager/mio/mio-memory.c 40 lines changed, 20 insertions(+), 20 deletions(-) =================================================================== @@ -73,34 +73,34 @@ mem_free (MIO *mio)
static gsize mem_read (MIO *mio, - void *ptr, + void *ptr_, gsize size, gsize nmemb) { gsize n_read = 0;
if (size != 0 && nmemb != 0) { - if (mio->impl.mem.ungetch != EOF) { - *((guchar *)ptr) = (guchar)mio->impl.mem.ungetch; - mio->impl.mem.ungetch = EOF; - mio->impl.mem.pos++; - if (size == 1) { - n_read++; - } else if (mio->impl.mem.pos + (size - 1) <= mio->impl.mem.size) { - memcpy (&(((guchar *)ptr)[1]), - &mio->impl.mem.buf[mio->impl.mem.pos], size - 1); - mio->impl.mem.pos += size - 1; - n_read++; - } + gsize size_avail = mio->impl.mem.size - mio->impl.mem.pos; + gsize copy_bytes = size * nmemb; + guchar *ptr = ptr_; + + if (size_avail < copy_bytes) { + copy_bytes = size_avail; } - for (; n_read < nmemb; n_read++) { - if (mio->impl.mem.pos + size > mio->impl.mem.size) { - break; - } else { - memcpy (&(((guchar *)ptr)[n_read * size]), - &mio->impl.mem.buf[mio->impl.mem.pos], size); - mio->impl.mem.pos += size; + + if (copy_bytes > 0) { + n_read = copy_bytes / size; + + if (mio->impl.mem.ungetch != EOF) { + *ptr = (guchar) mio->impl.mem.ungetch; + mio->impl.mem.ungetch = EOF; + copy_bytes--; + mio->impl.mem.pos++; + ptr++; } + + memcpy (ptr, &mio->impl.mem.buf[mio->impl.mem.pos], copy_bytes); + mio->impl.mem.pos += copy_bytes; } if (mio->impl.mem.pos >= mio->impl.mem.size) { mio->impl.mem.eof = TRUE;
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).