aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-04-26 23:42:32 +0000
committerrowanbeentje <rowan@beent.je>2010-04-26 23:42:32 +0000
commit1d7de2c00dae782992e1c082fbf3e98fe3666b88 (patch)
tree2433baaa13234e09732d2e9f6e127a88674e5273
parent4826a8a8523690c063fd25797a3d7d232043f31a (diff)
downloadsequelpro-1d7de2c00dae782992e1c082fbf3e98fe3666b88.tar.gz
sequelpro-1d7de2c00dae782992e1c082fbf3e98fe3666b88.tar.bz2
sequelpro-1d7de2c00dae782992e1c082fbf3e98fe3666b88.zip
- Improve threading of SPFileHandle to achieve much faster writing due to increased separation of the writing thread. This results in a up-to 1.2x faster MySQL dump for fast servers, and makes SPFileHandle faster than NSFileHandle for writing data (either directly or GZIP compressed).
-rw-r--r--Source/SPFileHandle.h1
-rw-r--r--Source/SPFileHandle.m39
2 files changed, 31 insertions, 9 deletions
diff --git a/Source/SPFileHandle.h b/Source/SPFileHandle.h
index 05a8da0e..05e05dd5 100644
--- a/Source/SPFileHandle.h
+++ b/Source/SPFileHandle.h
@@ -44,6 +44,7 @@
int fileMode;
BOOL dataWritten;
+ BOOL allDataWritten;
BOOL fileIsClosed;
BOOL useGzip;
}
diff --git a/Source/SPFileHandle.m b/Source/SPFileHandle.m
index e0838a6d..bceae2aa 100644
--- a/Source/SPFileHandle.m
+++ b/Source/SPFileHandle.m
@@ -51,6 +51,8 @@
- (id) initWithFile:(void *)theFile fromPath:(const char *)path mode:(int)mode
{
if (self = [super init]) {
+ dataWritten = NO;
+ allDataWritten = YES;
fileIsClosed = NO;
wrappedFile = theFile;
@@ -216,9 +218,12 @@
if (fileIsClosed) [NSException raise:NSInternalInconsistencyException format:@"Cannot write to a file handle after it has been closed"];
// Add the data to the buffer
- pthread_mutex_lock(&bufferLock);
- [buffer appendData:data];
- bufferDataLength += [data length];
+ if ([data length]) {
+ pthread_mutex_lock(&bufferLock);
+ [buffer appendData:data];
+ allDataWritten = NO;
+ bufferDataLength += [data length];
+ }
// If the buffer is large, wait for some to be written out
while (bufferDataLength > SPFH_MAX_WRITE_BUFFER_SIZE) {
@@ -235,7 +240,7 @@
- (void) synchronizeFile
{
pthread_mutex_lock(&bufferLock);
- while (bufferDataLength) {
+ while (!allDataWritten) {
pthread_mutex_unlock(&bufferLock);
usleep(100);
pthread_mutex_lock(&bufferLock);
@@ -302,17 +307,33 @@
continue;
}
+ // Copy the data into a local buffer
+ NSData *dataToBeWritten = [NSData dataWithData:buffer];
+ [buffer setLength:0];
+ bufferDataLength = 0;
+ pthread_mutex_unlock(&bufferLock);
+
// Write out the data
long bufferLengthWrittenOut;
if (useGzip) {
- bufferLengthWrittenOut = gzwrite(wrappedFile, [buffer bytes], bufferDataLength);
+ bufferLengthWrittenOut = gzwrite(wrappedFile, [dataToBeWritten bytes], [dataToBeWritten length]);
} else {
- bufferLengthWrittenOut = fwrite([buffer bytes], 1, bufferDataLength, wrappedFile);
+ bufferLengthWrittenOut = fwrite([dataToBeWritten bytes], 1, [dataToBeWritten length], wrappedFile);
}
- // Update the buffer
- CFDataDeleteBytes((CFMutableDataRef)buffer, CFRangeMake(0, bufferLengthWrittenOut));
- bufferDataLength = 0;
+ // Restore data to the buffer if it wasn't written out
+ pthread_mutex_lock(&bufferLock);
+ if (bufferLengthWrittenOut < [dataToBeWritten length]) {
+ if ([buffer length]) {
+ long dataLengthToRestore = [dataToBeWritten length] - bufferLengthWrittenOut;
+ [buffer replaceBytesInRange:NSMakeRange(0, 0) withBytes:[[dataToBeWritten subdataWithRange:NSMakeRange(bufferLengthWrittenOut, dataLengthToRestore)] bytes] length:dataLengthToRestore];
+ bufferDataLength += dataLengthToRestore;
+ }
+
+ // Otherwise, mark all data as written if it has been - allows synching to hard disk.
+ } else if (![buffer length]) {
+ allDataWritten = YES;
+ }
pthread_mutex_unlock(&bufferLock);
}