diff options
author | jerenkrantz <jerenkrantz@13f79535-47bb-0310-9956-ffa450edef68> | 2004-08-02 09:47:48 +0000 |
---|---|---|
committer | jerenkrantz <jerenkrantz@13f79535-47bb-0310-9956-ffa450edef68> | 2004-08-02 09:47:48 +0000 |
commit | a9a4c27a2be8524b0de8b7d80060fa452b19dd21 (patch) | |
tree | b06153ee5dcfdc285096a0534ea9beb12f4a459b | |
parent | 054658eb7d0be25c6b0d5622591055b1daa304e8 (diff) | |
download | libapr-a9a4c27a2be8524b0de8b7d80060fa452b19dd21.tar.gz |
Improve apr_file_gets() performance on buffered files by not calling
apr_file_read() on each byte if we don't have to.
(mod_negotiation requests call apr_file_gets() for each line in the map file,
which can get to be quite expensive to have repeated memcpy()'s for one byte!)
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@65294 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | file_io/unix/readwrite.c | 66 |
2 files changed, 58 insertions, 11 deletions
@@ -1,4 +1,7 @@ Changes for APR 1.1 [Deferring these features when 1.0 is rolled out.] + + *) Improve apr_file_gets() performance on buffered files. [Justin Erenkrantz] + *) Win32: Fix bug in apr_socket_sendfile that interferred with Win32 LSPs. PR 23982 [Jan Bilek, Bill Stoddard] diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index 1e6a6e665..98a11421d 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -24,9 +24,6 @@ #define USE_WAIT_FOR_IO #endif -/* problems: - * 1) ungetchar not used for buffered files - */ APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) { apr_ssize_t rv; @@ -311,18 +308,65 @@ APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) return APR_SUCCESS; } - while (str < final) { /* leave room for trailing '\0' */ - nbytes = 1; - rv = apr_file_read(thefile, str, &nbytes); - if (rv != APR_SUCCESS) { - break; + /* If we have an underlying buffer, we can be *much* more efficient + * and skip over the apr_file_read calls. + */ + if (thefile->buffered) { + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_lock(thefile->thlock); + } +#endif + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->direction = 0; + thefile->bufpos = 0; + thefile->dataRead = 0; } - if (*str == '\n') { + + while (str < final) { /* leave room for trailing '\0' */ + /* Force ungetc leftover to call apr_file_read. */ + if (thefile->bufpos < thefile->dataRead && + thefile->ungetchar == -1) { + *str = thefile->buffer[thefile->bufpos++]; + } + else { + nbytes = 1; + rv = apr_file_read(thefile, str, &nbytes); + if (rv != APR_SUCCESS) { + break; + } + } + if (*str == '\n') { + ++str; + break; + } + ++str; + } + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_unlock(thefile->thlock); + } +#endif + } + else { + while (str < final) { /* leave room for trailing '\0' */ + nbytes = 1; + rv = apr_file_read(thefile, str, &nbytes); + if (rv != APR_SUCCESS) { + break; + } + if (*str == '\n') { + ++str; + break; + } ++str; - break; } - ++str; } + /* We must store a terminating '\0' if we've stored any chars. We can * get away with storing it if we hit an error first. */ |