1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 08:31:16 +02:00

* Refactoring: move sink/source buffering into separate classes.

* Buffer the HashSink.  This speeds up hashing a bit because it
  prevents lots of calls to the hash update functions (e.g. nix-hash
  went from 9.3s to 8.7s of user time on the closure of my
  /var/run/current-system).
This commit is contained in:
Eelco Dolstra 2011-12-15 16:19:53 +00:00
parent a67b8ae224
commit 5a1b9ed0aa
8 changed files with 125 additions and 90 deletions

View file

@ -8,7 +8,16 @@
namespace nix {
void FdSink::operator () (const unsigned char * data, unsigned int len)
BufferedSink::~BufferedSink()
{
/* We can't call flush() here, because C++ for some insane reason
doesn't allow you to call virtual methods from a destructor. */
assert(!bufPos);
if (buffer) delete[] buffer;
}
void BufferedSink::operator () (const unsigned char * data, size_t len)
{
if (!buffer) buffer = new unsigned char[bufSize];
@ -16,7 +25,7 @@ void FdSink::operator () (const unsigned char * data, unsigned int 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);
write(data, len);
break;
}
/* Otherwise, copy the bytes to the buffer. Flush the buffer
@ -29,31 +38,32 @@ void FdSink::operator () (const unsigned char * data, unsigned int len)
}
void FdSink::flush()
void BufferedSink::flush()
{
if (fd == -1 || bufPos == 0) return;
writeFull(fd, buffer, bufPos);
if (bufPos == 0) return;
write(buffer, bufPos);
bufPos = 0;
}
void FdSource::operator () (unsigned char * data, unsigned int len)
void FdSink::write(const unsigned char * data, size_t len)
{
writeFull(fd, data, len);
}
BufferedSource::~BufferedSource()
{
if (buffer) delete[] buffer;
}
void BufferedSource::operator () (unsigned char * data, size_t len)
{
if (!buffer) buffer = new unsigned char[bufSize];
while (len) {
if (!bufPosIn) {
/* Read as much data as is available (up to the buffer
size). */
checkInterrupt();
ssize_t n = read(fd, (char *) buffer, bufSize);
if (n == -1) {
if (errno == EINTR) continue;
throw SysError("reading from file");
}
if (n == 0) throw EndOfFile("unexpected end-of-file");
bufPosIn = n;
}
if (!bufPosIn) bufPosIn = read(buffer, bufSize);
/* Copy out the data in the buffer. */
size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
@ -64,7 +74,20 @@ void FdSource::operator () (unsigned char * data, unsigned int len)
}
void writePadding(unsigned int len, Sink & sink)
size_t FdSource::read(unsigned char * data, size_t len)
{
ssize_t n;
do {
checkInterrupt();
n = ::read(fd, (char *) data, bufSize);
} while (n == -1 && errno == EINTR);
if (n == -1) throw SysError("reading from file");
if (n == 0) throw EndOfFile("unexpected end-of-file");
return n;
}
void writePadding(size_t len, Sink & sink)
{
if (len % 8) {
unsigned char zero[8];
@ -103,7 +126,7 @@ void writeLongLong(unsigned long long n, Sink & sink)
void writeString(const string & s, Sink & sink)
{
unsigned int len = s.length();
size_t len = s.length();
writeInt(len, sink);
sink((const unsigned char *) s.c_str(), len);
writePadding(len, sink);
@ -118,11 +141,11 @@ void writeStringSet(const StringSet & ss, Sink & sink)
}
void readPadding(unsigned int len, Source & source)
void readPadding(size_t len, Source & source)
{
if (len % 8) {
unsigned char zero[8];
unsigned int n = 8 - (len % 8);
size_t n = 8 - (len % 8);
source(zero, n);
for (unsigned int i = 0; i < n; i++)
if (zero[i]) throw SerialisationError("non-zero padding");
@ -162,7 +185,7 @@ unsigned long long readLongLong(Source & source)
string readString(Source & source)
{
unsigned int len = readInt(source);
size_t len = readInt(source);
unsigned char * buf = new unsigned char[len];
AutoDeleteArray<unsigned char> d(buf);
source(buf, len);