Construct native JS array/strings in C for fs.async.list callback.

Converting from JS-cocoa wrapper values for every element in the array appears to be very slow. Here we construct native JS datatypes and it's much faster. This is very messy and leaky and needs to be cleaned up if we want to keep it.
This commit is contained in:
Nathan Sobo
2012-01-03 22:47:20 -07:00
parent 7ba7ba2c81
commit faa39f6bdb
3 changed files with 48 additions and 31 deletions

View File

@@ -125,34 +125,53 @@
dispatch_queue_t mainQueue = dispatch_get_main_queue();
JSValueProtect(self.jscocoa.ctx, jsFunction.value);
dispatch_async(backgroundQueue, ^{
NSFileManager *fm = [NSFileManager defaultManager];
NSMutableArray *paths = [NSMutableArray array];
if (recursive) {
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath:path];
dispatch_async(backgroundQueue, ^{
NSFileManager *fm = [NSFileManager defaultManager];
NSString *subpath;
while (subpath = [enumerator nextObject]) {
[paths addObject:[path stringByAppendingPathComponent:subpath]];
}
} else {
NSError *error = nil;
NSArray *subpaths = [fm contentsOfDirectoryAtPath:path error:&error];
if (error) {
NSLog(@"ERROR %@", error.localizedDescription);
return;
}
for (NSString *subpath in subpaths) {
[paths addObject:[path stringByAppendingPathComponent:subpath]];
}
}
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
NSMutableArray *paths = [NSMutableArray array];
if (recursive) {
NSDirectoryEnumerator *enumerator = [fm enumeratorAtPath:path];
dispatch_sync(mainQueue, ^{
[self.jscocoa callJSFunction:jsFunction.value withArguments:[NSArray arrayWithObject:paths]];
JSValueUnprotect(self.jscocoa.ctx, jsFunction.value);
NSString *subpath;
while (subpath = [enumerator nextObject]) {
[paths addObject:[path stringByAppendingPathComponent:subpath]];
}
} else {
NSError *error = nil;
NSArray *subpaths = [fm contentsOfDirectoryAtPath:path error:&error];
if (error) {
NSLog(@"ERROR %@", error.localizedDescription);
return;
}
for (NSString *subpath in subpaths) {
[paths addObject:[path stringByAppendingPathComponent:subpath]];
}
}
NSLog(@"gathering paths: %f", CFAbsoluteTimeGetCurrent() - start);
// NS 1/3/12 - this is messy and also leaky... need to clean it up
start = CFAbsoluteTimeGetCurrent();
JSContextRef ctx = self.jscocoa.ctx;
JSObjectRef jsFunctionObject = JSValueToObject(ctx, jsFunction.value, NULL);
JSValueRef *jsStringCArray = malloc(sizeof(JSValueRef) * paths.count);
for (int i = 0; i < paths.count; i++) {
jsStringCArray[i] = JSValueMakeString(ctx, JSStringCreateWithCFString((CFStringRef)[paths objectAtIndex:i]));
}
JSValueRef jsStringJSArray = (JSValueRef)JSObjectMakeArray(ctx, paths.count, jsStringCArray, NULL);
NSLog(@"building js array of strings: %f", CFAbsoluteTimeGetCurrent() - start);
dispatch_sync(mainQueue, ^{
JSValueRef args[] = { jsStringJSArray };
JSObjectCallAsFunction(ctx, jsFunctionObject, NULL, 1, args, NULL);
// jscocoa wrapper is slow
// [self.jscocoa callJSFunction:jsFunction.value withArguments:[NSArray arrayWithObject:paths]];
JSValueUnprotect(self.jscocoa.ctx, jsFunction.value);
});
});
});
}
- (BOOL)isFile:(NSString *)path {

View File

@@ -6,13 +6,12 @@ class Project
constructor: (@url) ->
getFilePaths: ->
everythingMeasure = measure "Everything"
everythingMeasure = measure "getFilePaths"
projectUrl = @url
fs.async.list(@url, true).pipe (urls) ->
filterMeasure = measure "Filter out non-files"
urls = (url.replace(projectUrl, "") for url in urls when fs.isFile(url))
filterMeasure.stop()
everythingMeasure.stop()
urls

View File

@@ -89,10 +89,9 @@ module.exports =
async:
list: (path, recursive) ->
deferred = $.Deferred()
$atomController.contentsOfDirectoryAtPath_recursive_onComplete path, recursive, (result) ->
subpathMeasure = measure 'toString everything'
subpaths = (subpath.toString() for subpath in result)
subpathMeasure.stop()
cMeasure = measure 'time spent in obj-c'
$atomController.contentsOfDirectoryAtPath_recursive_onComplete path, recursive, (subpaths) ->
cMeasure.stop()
deferred.resolve subpaths
deferred