Swift与Objective-C的性能比较

18

我只是在比较SwiftObjective-C的性能。为此,我使用NSDate来测量所需时间,但Swift和Objective-C之间存在很大差异。我仅运行了空的for循环100,000次。以下是我的代码:

在Objective-C中,

NSDate * start = [NSDate date];

for (int i=0; i<=100000; i++) {

}

NSDate * end = [NSDate date];

double timeTaken = [end timeIntervalSinceDate:start] * 1000;

timeTaken为0.24毫秒

在Swift中,

var start = NSDate()

    for i in 0...100000

    {

    }

    var end = NSDate()

    var timeTaken = end.timeIntervalSinceDate(start) * 1000

timeTaken在Swift中为74毫秒,与Objective-C相比有很大的差异。

我在测量方面做错了什么吗?


4
您可能想要在大约一百万次迭代的过程中完成此操作。 - Tim
我开始制作一个演示应用来测试性能这里。在我的研究中(使用排序),即使打开优化,Swift 速度大约慢3-4倍。 - Cezary Wojcik
1
哈哈,我不确定迭代空代码块会更慢是否能告诉任何人什么:D,除非这是应用程序的常见用例。您可以每秒渲染多少个精灵? - Jay
你应该测试一些操作的性能,例如我会尝试使用枚举方法枚举一个数组。你是在模拟器还是设备上运行? - Andrea
1
通过启用-Ofast模式,Swift代码将运行得更快,以去除运行时安全检查。 - mythz
6个回答

17

你在做的纯属无意义。这个循环的性能如何并不重要,因为它在真实代码中不会发生。基本区别在于,Swift 中循环将在每一步执行溢出检查,这是由于语言定义所必需的副作用。而在 Objective-C 中则不是这样。

至少你需要编写实际有意义的代码。

我进行了一些真正的测试,结果是:1. 在低级操作方面,Swift 和纯 C 的速度是可比的。2. 当发生溢出时,Swift 会终止程序,以便您可以注意到溢出,而 C 和 Objective-C 则会默默地给您提供无意义的结果。试试这个:

var i: Int = 0
var s: Double = 0.0

for (i in 1 .. 10_000_000_000) { s += Double (i * i) }

Swift会崩溃。(认为这是不好的人对编程一无所知)。同样的事情在Objective-C中将产生无意义的结果。用

替换循环。

for (i in 1 .. 10_000_000_000) { s += Double (i) * Double (i) }

并且两者运行速度相当。


5
我不说我所做的是无意义的还是有意义的。我知道这不是一个常见的用例。由于存在很大的差异,我的实际问题是“我的测量方式是否出了什么问题?”因为我对Objective-C和Swift都很陌生。 - user3714324
2
那么你对OP中的巨大差异有什么结论?“你的测量并不是真实情况”的回答并不是问题的答案。 - Ian Goldby
9
Swift会崩溃。(认为这是坏事的人对编程一窍不通)。我认为那些做出如此笼统概括的人,在自己直接经验领域之外对编程了解甚少... :-) - Ian Goldby
5
"Swift将会崩溃。(任何认为这是坏事的人对编程一窍不通。)" 实际上相反,Swift 不应该只是“崩溃”。它应该停止运行并生成详细的错误消息来帮助您跟踪问题。实际上这可能就是发生的情况,如果是这样,您应该重新表达那句话,因为单词“崩溃”通常不指提供默认的多个有用诊断信息的行为(例如“分段错误”)。 - Bakuriu
1
有人能解释一下后者为什么更好吗?Double(i*i)有什么问题吗? - Sam D20
显示剩余3条评论

8

我对使用本地Swift数组和字符串与Objective-C可变数组和NSString进行了一些排序函数测试。

该函数对1000个字符串进行排序,执行了约一百万次字符串比较并打乱了数组。

结果如下:

  • Objective-C(使用原始整数和布尔值):0.32秒

  • Objective-C(使用NSNumber的整数和布尔值):0.45秒

  • 调试模式下的Swift:13秒 :)

  • 优化级别为(最快[-O])的Swift:1.32秒

  • 优化级别为(最快,未经检查的[-Ofast])的Swift:0.67秒

似乎在最快模式下,Swift已经接近Objective-C的速度,但仍不如苹果所声称的那么快。

这是我使用的排序代码:

Swift:

var strFile = String.stringWithContentsOfFile("1000strings.txt", encoding: NSUTF8StringEncoding, error: nil)
var strings:String[] = strFile!.componentsSeparatedByString("\n")
var startDate = NSDate()
var shouldLoopAgain = true
var numberOfLoops = 0
while shouldLoopAgain {
    shouldLoopAgain = false
    ++numberOfLoops
    for var i = 0; i < strings.count-1; ++i {
        if (strings[i] > strings[i+1]) {
            let temp = strings[i]
            strings[i] = strings[i+1]
            strings[i+1] = temp;
            if !shouldLoopAgain {
                shouldLoopAgain = true
            }
        }
    }
}
var time = NSDate().timeIntervalSinceDate(startDate)

Objective C 中的原始布尔值和整数

NSMutableArray *strings = [NSMutableArray arrayWithArray:[strFile componentsSeparatedByString:@"\n"]];
NSDate *startDate = [NSDate date];
BOOL shouldLoopAgain = YES;
int numberOfLoops = 0;
while (shouldLoopAgain) {
    shouldLoopAgain = NO;
    ++numberOfLoops;
    for (int i = 0; i < strings.count-1; ++i) {
        if ([strings[i] compare:strings[i+1]] == NSOrderedDescending) {
            NSString *temp = strings[i];
            strings[i] = strings[i+1];
            strings[i+1] = temp;
            if (!shouldLoopAgain) {
                shouldLoopAgain = YES;
            }
        }
    }
}

NSTimeInterval time = [[NSDate date] timeIntervalSinceDate:startDate];

使用NSNumber处理Objective C中的布尔值和整数

NSDate *startDate = [NSDate date];
NSNumber *shouldLoopAgain = @YES;
NSNumber *numberOfLoops = @(0);
while ([shouldLoopAgain boolValue]) {
    shouldLoopAgain = @NO;
    numberOfLoops = @([numberOfLoops intValue]+1);
    for (NSNumber *i = 0; [i intValue] < strings.count-1; i = @([i intValue]+1)) {
        if ([strings[[i intValue]] compare:strings[[i intValue]+1]] == NSOrderedDescending) {
            NSString *temp = strings[[i intValue]];
            strings[[i intValue]] = strings[[i intValue]+1];
            strings[[i intValue]+1] = temp;
            if (![shouldLoopAgain boolValue]) {
                shouldLoopAgain = @YES;
            }
        }
    }
}
NSTimeInterval time = [[NSDate date] timeIntervalSinceDate:startDate];

5

默认情况下,在调试模式下,编译器的优化级别设置为 None [-Onone]...

将其更改为 Fastest [-O](与发布相同)会产生以下结果:

Enter image description here


如果你将设置为“最快,未检查[-0fast]”,那么就有更快的级别了...这个级别接近于Objective C的速度,但仍然比它慢。 - Matej Ukmar
-O 无论如何都更快。Objective C 花费了约0.24毫秒,而Swift花费了约0.07毫秒。 - liamnichols

2

尝试启用优化进行编译。如果这不改变情况,请向Apple报告错误。Swift仍处于测试阶段,因此可能存在问题。


性能问题算不算是一个 bug?我认为它的功能符合预期,只是速度比预期慢了一些。 - limon
7
比预期慢绝对算作一个bug! - Catfish_Man

2
我认为目前还不能运行这些测试并确定Swift 1.0是比Objective-C更快还是更慢。整个Swift语言仍在开发中,语法和语言实现的方式正在改变。从Xcode 6 Beta 2和3之间的语言变化可以看出这一点,如果您查看Apple Dev论坛,可以看到正在开发该语言的苹果工程师明确表示某些内容尚不完整或未优化,并且在Swift 1.0发布之前不会完成,这应该与Xcode 6的公共发布同时进行。

因此,我并不是说现在做这些测试没有价值,但在Swift 1.0最终确定之前,我们无法对最终性能做出任何结论。


1

看一下这个https://softwareengineering.stackexchange.com/questions/242816/how-can-swift-be-so-much-faster-than-objective-c-in-these-comparisonshttp://www.splasmata.com/?p=2798 教程,也许你可以得到答案。但主要的是Swift语言仍处于测试阶段。而且苹果公司并没有自信地宣布Swift在所有情况下都比Objective-C更快。苹果公司告诉我们基于平均性能。我的观点是,如果在某些情况下Objective-C比Swift更快,并不意味着Swift的整体表现更慢。我们只需给予苹果公司更多时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接