From b2ff57467874e1c0cfad146a76acf0d9f3a0084c Mon Sep 17 00:00:00 2001 From: Devin Hussey Date: Fri, 8 Jun 2018 12:38:19 -0400 Subject: [PATCH] files: speed up reading by using getc_unlocked() instead of getc() Unlike glibc, which in getc() locks the file only when it is needed, FreeBSD and Bionic libc will always lock the file, causing a massive slowdown, as the system has to create and destroy a mutex each time getc() is called. Avoid that massive overhead by locking the file before starting to read and unlocking it after reading is complete, and using getc_unlocked() to read each byte. This makes reading on FreeBSD/macOS and Android anywhere from 2 to 6 times faster, and on glibc roughly seventy percent faster. This partially addresses https://savannah.gnu.org/bugs/?50406. Signed-off-by: Devin Hussey --- src/files.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index d0b0d7cb..41166230 100644 --- a/src/files.c +++ b/src/files.c @@ -760,8 +760,12 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable) topline = make_new_node(NULL); bottomline = topline; + /* Lock the file before starting to read it, to avoid the overhead + * of locking it for each single byte that we read from it. */ + flockfile(f); + /* Read the entire file into the new buffer. */ - while ((input_int = getc(f)) != EOF) { + while ((input_int = getc_unlocked(f)) != EOF) { input = (char)input_int; /* If it's a *nix file ("\n") or a DOS file ("\r\n"), and file @@ -828,6 +832,9 @@ void read_file(FILE *f, int fd, const char *filename, bool undoable) #endif } + /* We are done with the file, unlock it. */ + funlockfile(f); + /* Perhaps this could use some better handling. */ if (ferror(f)) nperror(filename);