From faa39f6bdb35731411eaa0d55bdd708af52b70eb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 3 Jan 2012 22:47:20 -0700 Subject: [PATCH] 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. --- Atom/Classes/AtomController.m | 69 ++++++++++++++++++++++------------- src/atom/project.coffee | 3 +- src/stdlib/fs.coffee | 7 ++-- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/Atom/Classes/AtomController.m b/Atom/Classes/AtomController.m index cb10a444f..1784f2e6c 100644 --- a/Atom/Classes/AtomController.m +++ b/Atom/Classes/AtomController.m @@ -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 { diff --git a/src/atom/project.coffee b/src/atom/project.coffee index 25ecf01ad..08ce5a452 100644 --- a/src/atom/project.coffee +++ b/src/atom/project.coffee @@ -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 diff --git a/src/stdlib/fs.coffee b/src/stdlib/fs.coffee index ea9053275..9d36634fa 100644 --- a/src/stdlib/fs.coffee +++ b/src/stdlib/fs.coffee @@ -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