Edited at

SwiftのprintlnはNSLogの10倍くらい高速

More than 3 years have passed since last update.


追記

以下、パフォーマンスのみについて言及しています。

本記事を書いた後、それ以外のNSLogとprintlnの違いに気付きつつ放置していましたが、この記事のAnswerがすごくよくまとまっていたので貼っておきます。

Swift: print() vs println() vs NSLog() - Stack Overflow


本文

どうしてSwiftでは既存のNSLogに加えて、printlnが増えたのだろう?

基本的にprintln使うべきな雰囲気は感じるけど、実際にメリットは?と思って調べました。

一つはジェネリクス使って定義されているので、文字列以外も気にせずに突っ込めるところだと思います。

func println<T>(object: T)

FOUNDATION_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);

で、ここからが本題です。

遅いと悪評高いNSLogでしたが、もしかしたらそれも解決されている?と思って測ってみました。

※Xcode6 beta6の結果です


10000回ループ.swift

let now = NSDate().timeIntervalSince1970

for i in 0...10000 {
println("hoge") // NSLog("hoge")でも試した
}
let elapsed = NSDate().timeIntervalSince1970 - now
println("elapsed: \(elapsed)")

シミュレーターで試したところ手元の環境では下記のような結果で、10倍くらい高速でした(実機でもほぼ同じでした)

所要時間

println
0.2秒前後

NSLog
2.3秒前後

じゃあObjective-Cでも使えるようにしようと思って何となくそれっぽいのを作成。

@objc

class Util {
class func NSLog(message: String) { // ジェネリクス使うとObjective-Cから見えない
println(message)
}
}

+(void)loopPrint {

NSTimeInterval now = [NSDate date].timeIntervalSince1970;
for (NSUInteger i = 0; i < 10000; i++) {
[Util NSLog:@"hoge"];
}
NSTimeInterval elapsed = [NSDate date].timeIntervalSince1970 - now;
[Util NSLog:[NSString stringWithFormat:@"elapsed: %f", elapsed]];
}

Objective-CでSwiftコードを挟んで実行しても10倍高速の同様の結果になりました。(呼び出しコスト分、少し時間かかるかな?という感じでしたが)

そして、ここまで書いた後に気づきましたが、単に速くしたいなら、以下のようなものを定義でも良いですね。

こちらもprintlnと同じかprintfの方が若干速かったです。

+(void)NSLog2:(NSString*)message {

printf("%s\n", [message UTF8String]);
}
// あるいは
#define NSLog2(message) printf("%s\n", [(message) UTF8String])

と、Objective-Cへの横展開はprintln使わなくても良いじゃんと自己完結しましたが、とりあえず上で書いたprintln版とほぼ同じ結果だったので、printlnは良く出来てますね。