You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中多次调用Decimal的formatted()方法为何性能逐渐下降?

问题:Decimal.formatted() 重复调用性能持续下降的原因

我需要给整数做三位分隔,所以用了Decimal类型的formatted()方法。但每次对随机整数调用这个方法100,000次时,性能会越来越差,想知道这是为什么。

测试代码

import Foundation

/// 计时函数
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

核心原因分析

这种性能持续下降的现象,本质是**formatted()方法依赖的系统本地化缓存机制出现了内存累积或资源泄漏**,具体拆解:

  • 本地化对象缓存膨胀:formatted()默认使用当前系统的本地化配置,每次调用都会隐式创建或复用NumberFormatter相关的本地化上下文。高频循环中,这些对象的缓存未被正确回收,内存中累积大量未释放的格式化条目,后续调用需要在臃肿的缓存中查找或创建对象,耗时递增。
  • 随机数范围的放大效应:每次生成的随机整数覆盖0到Int.max的全范围,Decimal格式化逻辑需要处理不同位数的数字,触发更多不同的格式化规则缓存条目,进一步加速缓存膨胀,提升后续调用的查找和计算成本。
  • ARC延迟回收的叠加:Swift的ARC虽能管理内存,但系统框架内部的本地化对象可能持有外部无法控制的强引用,这些对象不会在循环结束后立即释放,多次循环叠加后内存占用持续上升,间接拖慢整体执行速度。

优化方案

要解决性能问题,直接复用NumberFormatter对象即可避免重复创建和缓存膨胀,同时满足三位分隔的需求:

import Foundation

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")
}

// 预先创建并配置NumberFormatter,复用同一个实例
let formatter = NumberFormatter()
formatter.numberStyle = .decimal

calculateTime {
  for _ in 0...100_000 {
    _ = formatter.string(from: NSNumber(value: Int.random(in: 0...Int.max)))
  }
}
calculateTime {
  for _ in 0...100_000 {
    _ = formatter.string(from: NSNumber(value: Int.random(in: 0...Int.max)))
  }
}

复用NumberFormatter后,每次调用仅使用同一个格式化上下文,不会产生缓存膨胀问题,多次执行的耗时会保持稳定。

内容的提问来源于stack exchange,提问作者Mac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 20:16:06