为什么 first.split(separator: " ").map { Int(String($0))!} 比 first.split(separator: " ").map { Int($0)!} 好?

Why is first.split(separator: " ").map { Int(String($0))!} better than first.split(separator: " ").map { Int($0)!}?

import Foundation

let first = readLine()! // input : 10 20 30

processTime {
    first.split(separator: " ").map { Int([=12=])! }
}
processTime {
    first.split(separator: " ").map { Int(String([=12=]))! }
}

func processTime(blockFunction: () -> ()) {
    let startTime = CFAbsoluteTimeGetCurrent()
    blockFunction()
    let processTime = CFAbsoluteTimeGetCurrent() - startTime
    print("performance = \(processTime)")
}

性能 = 0.0012700557708740234 => Int($0)!

性能=0.000843048095703125 => Int(String($0))!

我是用map转Int的。但是当我将它转换为“Int(String($0))!”时花费的时间更少。我想知道为什么。

split返回的不是字符串,而是子串,所以Int([=12=])是把子串转成整数,Int(String([=13=]))是把子串转成字符串,再转成一个整数。

查看这两个演绎版的反汇编,它们调用了不同的 Int.init? 方法。但是装配中发生了很多事情,所以很难说这是否是唯一的区别,或者在后台发生的其他一些事情是否也会产生一些适度的影响。

但是,可以肯定地说,将 String 转换为 Int 比处理子字符串更有效。话虽这么说,我会坚持使用更简洁的代码,而不用担心这种微不足道的差异,除非这种差异(以千分之十秒为单位)将是 material(即你正在做数百万次,代码中其他地方没有其他东西可能有更多 material 优化机会等)。正如 Donald Knuth 所说:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.


顺便说一句,在衡量性能时,而不是衡量单个调用,而是执行数百万次并查看它们的比较情况。此外,在测试性能时,您可能还想尝试随机化执行测试的顺序,重复多次,以确保执行顺序不会影响性能。最后,确保您测试的是优化发布版本,而不是调试版本。

另外,单元测试有一个measure比较性能的方法,重复测试十次:

class ConversionBenchmarkTests: XCTestCase {    
    let input = "10 20 30"
    let count = 100_000

    func testInt() throws {
        measure {
            for _ in 0 ..< count {
                let result = input.split(separator: " ").map { Int([=10=])! }
                XCTAssertEqual(result.count, 3)
            }
        }
    }

    func testString() throws {
        measure {
            for _ in 0 ..< count {
                let result = input.split(separator: " ").map { Int(String([=10=]))! }
                XCTAssertEqual(result.count, 3)
            }
        }
    }
}

String 再现速度是原来的两倍: