diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-12-14T23·30+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-12-14T23·30+0000 |
commit | 3a48282b0681d68147e18f7464eaddf1d188c3be (patch) | |
tree | 43a5e7b6a16a5fb3ccd5991a30e2214df697d40a /src/libutil | |
parent | 893cac140232478e3ce9640ccf31dbfbfc2434c0 (diff) |
* Buffer writes in FdSink. This significantly reduces the number of
system calls / context switches when dumping a NAR and in the worker protocol.
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/serialise.cc | 25 | ||||
-rw-r--r-- | src/libutil/serialise.hh | 19 |
2 files changed, 37 insertions, 7 deletions
diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 9b422271323f..66a64a6be4c8 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -9,7 +9,30 @@ namespace nix { void FdSink::operator () (const unsigned char * data, unsigned int len) { - writeFull(fd, data, len); + if (!buffer) buffer = new unsigned char[bufSize]; + + while (len) { + /* Optimisation: bypass the buffer if the data exceeds the + buffer size and there is no unflushed data. */ + if (bufPos == 0 && len >= bufSize) { + writeFull(fd, data, len); + break; + } + /* Otherwise, copy the bytes to the buffer. Flush the buffer + when it's full. */ + size_t n = bufPos + len > bufSize ? bufSize - bufPos : len; + memcpy(buffer + bufPos, data, n); + data += n; bufPos += n; len -= n; + if (bufPos == bufSize) flush(); + } +} + + +void FdSink::flush() +{ + if (fd == -1 || bufPos == 0) return; + writeFull(fd, buffer, bufPos); + bufPos = 0; } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 0e797d63bca9..711bd5e6c7ce 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -28,22 +28,29 @@ struct Source }; -/* A sink that writes data to a file descriptor. */ +/* A sink that writes data to a file descriptor (using a buffer). */ struct FdSink : Sink { int fd; + unsigned int bufSize, bufPos; + unsigned char * buffer; - FdSink() + FdSink() : fd(-1), bufSize(32 * 1024), bufPos(0), buffer(0) { } + + FdSink(int fd, unsigned int bufSize = 32 * 1024) + : fd(fd), bufSize(bufSize), bufPos(0), buffer(0) { - fd = -1; } - - FdSink(int fd) + + ~FdSink() { - this->fd = fd; + flush(); + if (buffer) delete[] buffer; } void operator () (const unsigned char * data, unsigned int len); + + void flush(); }; |