macOS中Swift Decimal性能为何比Python Decimal慢2.5倍?
Swift Decimal vs Python Decimal 性能差异排查与优化建议
测试环境与结果
环境配置
- macOS Sonoma 14.5
- Xcode 15.4
- Apple M3 Max芯片
- Python 3.12
测试结果
- Double类型运算:Python完成50亿次计算耗时241秒;Swift仅需1.3秒,性能提升约191倍。
- Decimal高精度运算:Python完成2亿次计算耗时73秒;Swift需186秒,且尾数精度更低,性能慢约2.6倍。
更新说明
已在Swift中使用GMP库运行相同测试,速度比Swift Decimal快约10倍(为当前场景下的性能上限),但仍困惑为何Python Decimal比Swift Decimal快2.5倍。
已在Release模式下编译Swift代码,寻求问题排查建议或高效高精度数学库推荐。
测试代码
Python代码
import random import time import math from time import process_time, time from decimal import * REPEAT_CALC = 10000 INPUTS_COUNT = 20000 inputs = [] calculations = 0 functions = 0 for i in range(0, INPUTS_COUNT): input = (Decimal(random.randint(1, 10)), Decimal(random.randint(1, 10))) inputs.append(input) def calculate(x, y): global calculations global functions Decimal_pi = Decimal(math.pi) functions += 1 hypo = Decimal(0) for i in range(0, REPEAT_CALC): hypo = (x / Decimal_pi) * (y / Decimal_pi) calculations += 1 return hypo def get_calculations(inputs): solutions = [] for input in inputs: solutions.append(calculate(input[0], input[1])) return solutions time_started = time() ptime_started = process_time() solutions = get_calculations(inputs) ptime_ended = process_time() time_ended = time() print("functions:", functions, "calculations:", calculations, "duration:", (time_ended - time_started)*1000, "ms cputime:", (ptime_ended - ptime_started) * 1000.0, "ms pi:", Decimal(math.pi))
Swift代码
import Foundation import Cocoa let REPEAT_CALC: Int = 10000 let INPUTS_COUNT: Int = 20000 let clock = ContinuousClock() var inputs: [(Decimal, Decimal)] = [(Decimal, Decimal)]() inputs.reserveCapacity(INPUTS_COUNT) var calculations: Int = 0 var functions: Int = 0 for _ in 0 ..< INPUTS_COUNT { inputs.append((Decimal(Int.random(in: 1..<10)), Decimal(Int.random(in: 1..<10)))) } func calculate(x: Decimal, y: Decimal) -> Decimal { functions += 1 var hypo: Decimal = 0 for _ in 0 ..< REPEAT_CALC { hypo = (x/Decimal.pi) * (y/Decimal.pi) calculations += 1 } return hypo } func get_calculations(my inputs: [(Decimal, Decimal)]) -> [Decimal] { var solutions: [Decimal] = [] solutions.reserveCapacity(inputs.count) for input in inputs { solutions.append(calculate(x: input.0, y: input.1)) } return solutions } var solutions: [Decimal] = [] let time = clock.measure { solutions = get_calculations(my: inputs) } print("functions: \(functions) calculations: \(calculations) duration: \(Double(time.components.seconds) * 1000 + Double(time.components.attoseconds) * 1e-15)ms pi:", Decimal.pi)
排查建议
- 缓存常量减少重复计算:Swift代码中每次循环都访问
Decimal.pi,可将其提前缓存为常量,避免重复初始化开销:let pi = Decimal.pi func calculate(x: Decimal, y: Decimal) -> Decimal { // 后续用pi替代Decimal.pi } - 简化运算逻辑:将
(x/pi) * (y/pi)优化为x * y / (pi * pi),或者预计算1/(pi*pi)的倒数,减少除法操作(除法运算远慢于乘法):let invPiSquared = Decimal(1) / (pi * pi) // 循环内改为:hypo = x * y * invPiSquared - 检查编译优化选项:确认Release模式下已开启最高优化级别
-O,并针对Apple Silicon架构启用特定优化(如-target arm64-apple-macos14),关闭调试符号与断言。 - 减少全局变量开销:全局变量
calculations和functions的读写会带来原子操作开销,可改为局部变量并通过闭包返回统计值,或者使用UnsafeMutablePointer直接操作内存。 - 循环优化:使用Swift的
map替代手动for循环,让编译器进行自动循环展开与向量化优化;或者将循环逻辑内联到主函数,减少函数调用开销。
高效高精度数学库推荐
- GMP:已验证比Swift Decimal快10倍,是当前场景下的性能上限选择,需通过C桥接在Swift中集成,支持任意精度的整数与浮点数运算。
- DecimalSwift:第三方Swift Decimal实现,针对Swift生态优化,性能优于Foundation的NSDecimal,API更贴合Swift语法。
- Swift Numerics:苹果官方数值计算库,提供高性能的浮点数运算组件,可结合高精度库使用以优化特定场景。
- BigInt:专注于大整数运算的高性能库,若业务场景以整数运算为主,可优先选择。
内容的提问来源于stack exchange,提问作者nilgirian
相关产品推荐
相关产品推荐

