-2

I have a Swift app with an array of about ~100k strings. The array looks something like this:

let strings: [String] = [
    "a",
    "as",
    // 99,998 elements later...
    "zebra"
]

It takes nearly 6 minutes to build and run the app in the iOS Simulator. I've isolated the slow build time to the inclusion of this array in the project. Once built, subsequent launches are very fast (until I have to build again). What can I do to speed up the build process?

JWK
  • 3,345
  • 2
  • 19
  • 27
  • 3
    Put the data in a database. Do you really need 100,000 strings in memory at once? – rmaddy Mar 31 '15 at 04:44
  • For context, I'm filtering the (entire) array 1) for strings with a desired number of characters (e.g 4 or 7) and 2) for strings where all characters are contained in a preselected string (e.g "lifeline", where "file" would be a match, but "leaf" or "lifelines" wouldn't). I’d REALLY like to avoid having the extra complexity of a database, though I see how that would reduce compile time. – JWK Mar 31 '15 at 04:54
  • 4
    All of that can be done using a database. – rmaddy Mar 31 '15 at 04:56
  • I don't doubt it :) Any other suggestions though? Reading from a plain text file, for example, doesn't slow down compile time. That said, it may turn out to be very inefficient once the app is built. – JWK Mar 31 '15 at 05:03
  • 3
    Any approach that loads all 100,000 words into memory is a bad idea. – rmaddy Mar 31 '15 at 05:06
  • Put it in a database. If you're going to be querying strings for strings containing substrings, databases make this easier and optimize efficiency. Don't fight the idea of using a database in the name of simplicity. It will result in poor, inefficient code that takes 6 minutes to build – Ian Mar 31 '15 at 05:22
  • I should add that this is purely academic in nature–not something I plan to release, so a database really seems like overkill to me for that reason. I just gave the "reading from a plain text file" route a shot using [this gist](https://gist.github.com/klaas/4691612802f540b6a9c5). The app compiles almost immediately and the file is read / matching strings are appended to an array (around 600 elements) in about 5 seconds. This absolutely works for me. – JWK Mar 31 '15 at 05:24
  • If you search for "Swift expression too complex" here on SO or in the Apple Developer Forum then you'll find similar issues where expressions that seem to be simple fail (or take a long time) to compile. As I understand it, it has to do with the type inference system. It might be better with Xcode 6.3 beta. – Martin R Mar 31 '15 at 05:39
  • Hm, I have encountered that error before (though not in this project). I'm uncertain if it's a factor here, but I may try splitting the array into multiple lines just to see what happens. For now, the file based approach is working very well. – JWK Mar 31 '15 at 05:46
  • There is absolutely no need to argue, go with a database or just a textfile, anything external, anything else is just wrong and bad. – luk2302 Mar 31 '15 at 06:36
  • I completely agree, which is why I posted the question in the first place. The only point I was arguing for was a simpler solution than a database–one more suited to my needs. Like I said, the file based approach worked for me. – JWK Mar 31 '15 at 06:50

1 Answers1

0

Per the comments above, the best solution for me was to use a text file. A database would have worked too, though it would've added unnecessarily complexity in this case. The text file looks something like this:

a
as
...
zebra

The file is read using the StreamReader gist from this SO post. The code for doing so looks like this:

if let aStreamReader = StreamReader(path: "/path/to/file") {
    for word in aStreamReader {
        // This is where I'm testing the following conditions:
        // 1) Does the word have a specific number of characters (e.g. 4 or 7)?
        // 2) Do all the characters in the word exist in a stored string?
        // e.g "lifeline", where "file" would match, but "lifelines" wouldn't.
        // This code is only here for context.
        if contains(characterCountsToMatch, countElements(word)) {
            if stringToMatch.containsCharsInString(word) {
                matchingWords.append(word)
            }
        }
    }
}

The resulting matchingWords array contains only the necessary elements–about 600 in my case (not ~100k elements!). The application now compiles with no delay. Reading from the file and appending matches to the matchingWords array takes about 5 seconds, which is acceptable for my needs, but could be further optimized if needed.

Community
  • 1
  • 1
JWK
  • 3,345
  • 2
  • 19
  • 27