我需要将整数分成 3 位数字,并研究formatted()该Decimal类型的方法。对随机整数每次
调用该formatted()类型的方法100,000 次会逐渐降低性能。
我想知道为什么会发生这种情况。Decimal
import Foundation
/// https://stackoverflow.com/a/56381954
func calculateTime(block : (() -> Void)) {
let start = DispatchTime.now()
block()
let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime) / 1_000_000_000
print("Time: \(timeInterval) seconds")
}
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
Run Code Online (Sandbox Code Playgroud)
Time: 0.9492465 seconds
Time: 3.29213125 seconds
Time: 7.988363667 seconds
Time: 15.165178292 seconds
Time: 17.305036583 seconds
Time: 25.0114935 seconds
Time: 35.746310417 seconds
Time: 47.024551125 seconds
Run Code Online (Sandbox Code Playgroud)
虽然马特和马丁 R 是正确的,但他们实际上并没有指出罪魁祸首。当您使用“内存对象”调试器时,在函数执行时,您将看到这个非常有趣的图表:
因此,该函数formatted()会导致大量分配,主要是 类型的对象NSAutoLocale。
这暗示了进一步的问题:由于评估区域设置需要访问实际读取区域设置的文件,因此您还可能会遇到性能非常慢的情况。
因此,如果您也想加快速度,则应该显式使用预配置的区域设置对象,该对象分配一次且仅分配一次,然后将其用作参数来格式化字符串。
编辑:
为了证明我的假设,我创建了一个等效的陈述并将其与您的原始陈述进行了比较:
你原来的代码:
calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
Run Code Online (Sandbox Code Playgroud)
时间:9.674371748秒
使用单个语言环境的等效代码:
let locale = Locale()
calculateTime { for _ in 0...100_000 { _ = NSDecimalNumber(
value: Int.random(in: 0...Int.max))
.description(withLocale: locale)
} }
Run Code Online (Sandbox Code Playgroud)
时间:0.210493037秒
并且无需任何进一步的修改,重复调用改进的语句,您将得到:
Time: 0.224133942 seconds
Time: 0.238930039 seconds
Time: 0.214735965 seconds
Time: 0.220390686 seconds
Time: 0.212360066 seconds
Time: 0.207630215 seconds
Time: 0.205125154 seconds
Run Code Online (Sandbox Code Playgroud)
...
这是一个 Heisenbug:您自己通过测试工具使内存紧张而导致速度变慢。将您的测试线更改为:
calculateTime { for _ in 0...100_000 { autoreleasepool { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } } }
calculateTime { for _ in 0...100_000 { autoreleasepool { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } } }
calculateTime { for _ in 0...100_000 { autoreleasepool { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } } }
// ... and so on
Run Code Online (Sandbox Code Playgroud)