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

为何Swift中ClosedRange<Int>.contains性能比预期慢340万倍?

Swift中ClosedRange.contains(_: Sequence)性能异常的原因与解决方法

问题现象

使用Xcode 15.0.1(Swift 5)时,调用ClosedRange.contains(_ other: ClosedRange)的性能远低于手动边界比较逻辑,测试代码如下:

import Foundation

func measure(fn: @escaping ()->Void) -> CFAbsoluteTime {
    let startTime = CFAbsoluteTimeGetCurrent()
    fn()
    let endTime = CFAbsoluteTimeGetCurrent()
    return endTime - startTime
}

let r1: ClosedRange<Int> = 1222450723...1308640992
let r2: ClosedRange<Int> = 41218238...462709950

let dt_a = measure { let _ = r1.lowerBound <= r2.lowerBound && r1.upperBound >= r2.upperBound }
let dt_b = measure { let _ = r1.contains(r2) }

测试结果:

  • 手动边界比较(dt_a)耗时约95微秒
  • 调用contains(_:)(dt_b)耗时约326.9秒(Release模式下甚至达到356秒)
    两者性能差距超过340万倍。

原因解析

这是API语义误解导致的误用,并非Swift的Bug。

你调用的r1.contains(r2)并非专门用于判断“范围包含”的方法,而是Collection协议提供的contains<S>(_ other: S) -> Bool重载(其中S是序列,且元素类型与当前集合一致)。这个方法的语义是:检查当前集合是否包含另一个序列的所有元素。

由于ClosedRange遵循Collection协议,r2会被当作一个包含4亿多个元素的序列来遍历,逐个验证每个元素是否存在于r1中——这种实现完全不符合你预期的“范围边界比较”逻辑,因此导致了极端缓慢的执行速度。

解决方案

要判断一个ClosedRange是否完全包含另一个ClosedRange,直接使用边界比较逻辑即可,这是最高效的方式:

// 直接在代码中使用判断逻辑
let isContained = r1.lowerBound <= r2.lowerBound && r1.upperBound >= r2.upperBound

如果需要复用这个逻辑,可以给ClosedRange扩展一个专门的方法:

extension ClosedRange where Bound: Comparable {
    /// 判断当前范围是否完全包含另一个范围
    func fullyContains(_ other: ClosedRange<Bound>) -> Bool {
        return lowerBound <= other.lowerBound && upperBound >= other.upperBound
    }
}

// 使用方式
let isContained = r1.fullyContains(r2)

注意不要直接重载contains方法,避免和原有的API语义冲突,导致代码可读性下降。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:12:44