为什么每次调用Swift中Decimal类型的formated()方法时,它变得越来越慢?

gywdnpxw  于 2023-01-16  发布在  Swift
关注(0)|答案(2)|浏览(157)

我需要将整数分成3位数,并研究了Decimal类型的formatted()方法。
每次为随机整数调用Decimal类型的formatted()方法100,000次会逐渐降低性能。
我想知道为什么会发生这种情况。

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() } }
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
f87krz0w

f87krz0w1#

虽然matt和Martin R是正确的,但他们并没有真正指出问题的症结所在。当你使用"Memory Object"调试器时,当函数正在执行时,你会看到这个非常有趣的图表:

因此,函数formatted()会导致大量的分配,主要是NSAutoLocale类型的对象。
这暗示了进一步的问题:由于评估一个区域设置需要访问一个实际读取区域设置的 * 文件 *,因此您也可能会体验到非常慢的性能。
因此,如果您还想加快速度,则应该显式地使用预配置的locale对象,分配该对象一次,且仅分配一次,然后将其用作格式化字符串的参数。
编辑:
为了证明我的假设,我创建了一个等价的语句,并将其与您的原始语句进行了比较:
您的原始代码:

calculateTime { for _ in 0...100_000 { _ = Decimal(Int.random(in: 0...Int.max)).formatted() } }
    • 时间:9.674371748秒**

使用单个语言环境的等效代码:

let locale = Locale()
calculateTime { for _ in 0...100_000 { _ = NSDecimalNumber(
    value: Int.random(in: 0...Int.max))
    .description(withLocale: locale)
} }
    • 时间: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

...

r55awzrz

r55awzrz2#

这是一个海森堡:您使用测试工具占用了内存,从而导致速度减慢。请将测试行更改为:

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

相关问题