Quantcast
Channel: Eltima Dev
Viewing all articles
Browse latest Browse all 42

Speeding up Array’s Sorting in Swift

$
0
0

What’s up?

In my previous post I told you about the fix for compilation error in case optimization was enabled. And as I’ve already mentioned, I still haven’t succeeded in improving app’s performance. Today I’ll tell you how I found the reason for the poor performance and how I fixed it.

In my project, the list of files sorted by name should be displayed. When lists are sorted via string comparator, the performance is good enough. But if the files are sorted like in the Finder, performance drops dramatically in case array contains a big amount of elements.

For example, let’s take the contents of ~/Library/Preferences folder (1000 files in total) and sort the list with this code:

 filesArray.sort({ (item1:NSURL, item2:NSURL) -> Bool in

           let comparisonOptions:NSStringCompareOptions = NSStringCompareOptions.CaseInsensitiveSearch | NSStringCompareOptions.NumericSearch | NSStringCompareOptions.WidthInsensitiveSearch | NSStringCompareOptions.ForcedOrderingSearch;

           var str1:String = item1.path!.lastPathComponent
           var str2:String = item2.path!.lastPathComponent
       	
           var res = str1.compare(str2, options: comparisonOptions, range: str1.startIndex ..< str1.endIndex, locale: NSLocale.currentLocale())
       	
           return res == NSComparisonResult.OrderedAscending
       })

When using Xcode6 beta6 with the enabled optimization, it takes 5 seconds to sort the files. (Just to compare, it took about several minutes in beta5.) As you see, files sorting speed cannot be called acceptable anyway.

I decided to compare the sorting time of the method described above with the time of this method:

filesArray.sort( { $0.path!.lastPathComponent > $1.path!.lastPathComponent })

And it suddenly dawned on me that the problem could lie in calling the following Objcetive-C method from Swift too often:

 - compare:options:range:locale:

I decided to sort array using methods of NSArray class.

       var nsFilesArray = filesArray as NSArray
   	
       nsFilesArray = nsFilesArray.sortedArrayUsingComparator({(item1:AnyObject!, item2:AnyObject!) -> NSComparisonResult in
           let comparisonOptions:NSStringCompareOptions =
NSStringCompareOptions.CaseInsensitiveSearch |
NSStringCompareOptions.NumericSearch |
NSStringCompareOptions.WidthInsensitiveSearch |
NSStringCompareOptions.ForcedOrderingSearch; var str1:String = (item1 as NSURL).path!.lastPathComponent var str2:String = (item2 as NSURL).path!.lastPathComponent return str1.compare(str2, options: comparisonOptions, range: str1.startIndex ..< str1.endIndex, locale: NSLocale.currentLocale()) }) filesArray = nsFilesArray as Array

These changes result in sorting within only 0,02 seconds even when optimization is disabled. That is what I call adequate performance.

Note: This might prove to be not the best solution actually, as I had to call NSArray method.

Hope to come back to this issue after Xcode6 release. But at the moment, that is the most satisfactory resolving of the problem.

BTW, see in the last listing how closure can be easily transferred into the ordinary Objective-C method!

Subscribe here:

https://www.facebook.com/develtima
https://twitter.com/develtima


Viewing all articles
Browse latest Browse all 42

Trending Articles