即使使用 -Ofast,Swift 的字典也很慢

2024-01-01

我正在使用本质上实现缓存Dictionary在斯威夫特.表现远远低于我的预期。我读过其他一些问题,例如这是关于数组排序的 https://stackoverflow.com/questions/24101718/swift-performance-sorting-arrays这似乎表明-Ofast就是答案(如果您准备好接受它带来的变化)。然而,即使编译后-Ofast,性能与其他语言相比较差。我使用的是 Swift 1.0 版 (swift-600.0.34.4.8)。

下面是一个说明问题的简化示例:

import Foundation

class Holder {
    var dictionary = Dictionary<Int, Int>()

    func store(#key: Int, value: Int) {
        dictionary[key] = value
    }
}

let holder = Holder()

let items = 5000

for (var i: Int = 0; i < 5000; i++) {
    holder.store(key: i, value: i)
}

编译为-O3运行需要两秒多的时间:

xcrun swift -sdk $(xcrun --show-sdk-path --sdk macosx) -O3 Test.swift && time ./Test

real    0m2.295s
user    0m2.176s
sys     0m0.117s

编译用-Ofast产生 3-4 倍的改进:

xcrun swift -sdk $(xcrun --show-sdk-path --sdk macosx) -Ofast Test.swift && time ./Test

real    0m0.602s
user    0m0.484s
sys     0m0.117s

相比之下,这个 Java 实现:

import java.util.Map;
import java.util.HashMap;

public class Test {
    public static void main(String[] args) {
        Holder holder = new Holder();
        int items = 5000;
        for (int i = 0; i < items; i++) {
            holder.store(i, i);
        }
    }
}

class Holder {
    private final Map<Integer, Integer> map = new HashMap<Integer, Integer>();

    public void store(Integer key, Integer value) {
        map.put(key, value);
    }
}

又快了约 6 倍:

javac Test.java && time java Test

real    0m0.096s
user    0m0.088s
sys     0m0.021s

仅仅是复制的成本吗?Dictionary因为它已经突变并存储在Holder是什么导致 Swift 表现如此糟糕?去除Holder并访问Dictionary直接表明是这样的。

这段代码:

import Foundation

var dictionary = Dictionary<Int, Int>()

let items = 5000

for (var i: Int = 0; i < 5000; i++) {
    dictionary[i] = i
}

is 显著地 faster:

$ xcrun swift -sdk $(xcrun --show-sdk-path --sdk macosx) -O3 NoHolder.swift && time ./NoHolder

real    0m0.011s
user    0m0.009s
sys     0m0.002s

$ xcrun swift -sdk $(xcrun --show-sdk-path --sdk macosx) -Ofast NoHolder.swift && time ./NoHolder

real    0m0.011s
user    0m0.007s
sys     0m0.003s

虽然它提供了(希望)有趣的数据点,但在我的情况下直接访问字典是不可能的。我还可以做些什么来使用当前形式的 Swift 来接近这种性能水平吗?


TL;DR 这是测试版。

我认为现在的答案只是 Swift 处于测试阶段,工具也处于测试阶段,还有很多优化工作要做。在 Obj-C 中复制“Holder”类示例表明,即使它在相同的情况下速度也快得多-Ofast level.

@import Foundation;

@interface Holder : NSObject

@property NSMutableDictionary *dictionary;
- (void)storeValue:(NSInteger)value forKey:(NSString *)key;

@end

@implementation Holder

- (instancetype)init {
   self = [self initWithDict];
    return self;
}


- (instancetype)initWithDict {
    if (!self) {
        self = [super init];
        _dictionary = [NSMutableDictionary dictionary];
    }

    return self;
}

- (void)storeValue:(NSInteger)value forKey:(NSString *)key {
    [self.dictionary setValue:@(value) forKey:key];
}

@end

int main(int argc, const char * argv[]) {

    Holder *holder = [Holder new];

    for (NSInteger i = 0; i < 5000; i++) {
        [holder storeValue:i forKey:[NSString stringWithFormat:@"%ld", i]];
    }

}

Obj-C 很快就推出了。

time ./loop 

    real    0m0.013s
    user    0m0.006s
    sys     0m0.003s

与您给出的 NoHolder 示例在时间上的相似性很好地表明了 Obj-C 编译器正在进行多少优化。

看一下装配体-O3 and -OfastSwift 中的级别表明安全检查的数量存在很大差异。查看 Obj-C 汇编表明,需要执行的操作要少得多。由于使程序快速运行的关键是使其不需要做太多事情......

OS-X-Dos-Equis:~ joshwisenbaker$ wc -l objc.txt 
     159 objc.txt
OS-X-Dos-Equis:~ joshwisenbaker$ wc -l oFast.txt 
    3749 oFast.txt

(编辑:更新 Holder 类的最终确定结果。)

所以另一个有趣的问题是使用@final类定义上的装饰。如果您知道您的类永远不会被子类化,那么请尝试添加如下关键字:@final class Holder

正如您所看到的,它还以相同的方式编译时标准化了性能。

OS-X-Dos-Equis:~ joshwisenbaker$ swift -sdk $(xcrun --show-sdk-path --sdk macosx) -Ofast bench.swift && time ./bench

real    0m0.013s
user    0m0.007s
sys     0m0.003s

即使只使用-O3 the @final发挥魔力。

OS-X-Dos-Equis:~ joshwisenbaker$ swift -sdk $(xcrun --show-sdk-path --sdk macosx) -O3  bench.swift && time ./bench

real    0m0.015s
user    0m0.009s
sys 0m0.003s

同样,我认为您在性能方面看到的差异可能取决于编译时的当前优化级别。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

即使使用 -Ofast,Swift 的字典也很慢 的相关文章

  • UIDocumentInteractionController 显示空白 pdf

    我尝试使用 UIDocumentInteractionController PresentPreviewAnimated 方法在 iOS 设备上显示 pdf 但它一直显示空白文档 我认为这可能与字符编码有关 但我不确定 如果我使用 UIWe
  • 空 while 循环有什么影响?

    我知道这可能是一个有点 愚蠢 的问题 但有时 我只想循环直到条件为假 但我不喜欢让循环保持为空 所以代替 Visible true while IsRunning Visible false 我通常prefer while IsRunnin
  • Swift:将字符串转换为十六进制颜色代码

    我已经从数据库生成了用户 ID 格式类似于 XzSYoKJaqKYREkdB2dgwt0fLOPP2 我想用它来创建 UIColor 我找到了几个解决方案 https github com yeahdongcn UIColor Hex Sw
  • 如何在导航栏中添加右键?

    我有一个问题要在导航栏中添加右键 我有两个视图 视图 A 和视图 B 我添加了一个导航栏来查看A 之后我使用了self navigationController pushViewController显示视图 B 视图B的导航栏左侧自动显示一
  • CSV 解析 - Swift 4

    我正在尝试解析 CSV 但遇到一些问题 下面是我用来解析 CSV 的代码 let fileURL Bundle main url forResource test application data Sheet 1 withExtension
  • 如何将渐变应用于 iOS Swift 应用程序的背景视图

    我正在尝试应用渐变作为视图 故事板的主视图 的背景颜色 代码运行 但没有任何变化 我正在使用 xCode Beta 2 和 Swift 这是代码 class Colors let colorTop UIColor red 192 0 255
  • 在 Swift 中获取 UIImage 的主颜色

    我正在尝试在 Swift 中获取 UIImage 的主颜色 并尝试移植这段代码 https stackoverflow com questions 13694618 objective c getting least used and mo
  • 只读有运行时开销吗?

    出于某种原因 我一直认为readonly字段有与其相关的开销 我认为这是 CLR 跟踪是否存在readonly字段是否已初始化 这里的开销是一些额外的内存使用量 用于跟踪状态以及分配值时的检查 也许我这么认为是因为我不知道readonly字
  • .NET 中 UniqueQueue 和 UniqueReplacementQueue 集合最有效的实现

    考虑到入队和出队操作的速度同样重要 NET 中 UniqueQueue 和 UniqueReplacementQueue 集合最有效 就速度而言 的实现是什么 UniqueQueue是一个不可能出现重复的队列 因此 如果我将一个元素推送到队
  • Firestore 更新后仅获取文档一次

    我有一个 tableView 它从 Firestore 集合中获取所有文档 并且我只想在用户刷新 tableView 后将最后一个文档添加到 Firestore 时获取一次 然后我想删除侦听器 以便当用户刷新 tableView 时仅获取文
  • 检查定位服务是否开启

    我一直在对 CoreLocation 进行一些研究 最近 我遇到了一个在其他地方 但在 Objective C 和 iOS 8 中 已经讨论过的问题 我觉得问这个问题有点傻 但是如何在 iOS 9 上使用 swift 检查是否启用了位置服务
  • 在Python列表中交换元素的最快方法

    在Python中交换两个列表元素是否有比 L a L b L b L a 或者我必须求助于Cython http cython org or Weave http www scipy org Weave或类似的 看起来 Python 编译器
  • 在 Cocoa OS X AVPlayer 中播放 HLS (m3u8) - Swift

    基本上我正在尝试在 Cocoa Swift 中使用 AVPlayer 播放 m3u8 HLS Live Stream 我对这门语言比较陌生 所以基本上掌握了一些示例代码 http qiita com ono matope items 23d
  • 确定 SceneKit 中 SKVideoNode 的视频大小/长宽比

    如何从 AVPlayer 获取视频的视频大小来设置节点的几何大小 例如 我有一个具有宽度和高度的 SCNPlane let planeGeo SCNPlane width 5 height 5 所以现在我实例化我的视频播放器 let vid
  • 在没有预览窗口的情况下使用 AVCaptureVideoDataOutputSampleBufferDelegate

    我正在开发一个基于 Swift 的 macOS 应用程序 我需要捕获视频输入 但不将其显示在屏幕上 而不是显示视频 我想将缓冲的数据发送到其他地方进行处理 并最终显示它在 a 中的一个物体上SceneKit scene 我有一个Camera
  • 如何使用 NSUserDefaults 在 Swift 中存储自定义类的数组?

    我有一个名为的自定义类Person当某人输入信息时 它会存储有关某人的各种属性 class Person Person dictionary variable var name String var age String var html
  • 使用完成处理程序在 Swift 中调用连续动画

    我正在制作一个可以显示化学反应动画的应用程序 每个原子都是一个 SCNSphere 并通过 SCNActions 进行动画处理 我尝试使用 runAction 中的完成处理程序在当前操作完成后调用下一个动画 因为每个原子必须做出很多不同的运
  • 如何使用 Swift 使用 TouchID?

    Apple 为 iOS 8 的 TouchID 实现提供的文档采用 Objective C 语言 有 Swift 版本吗 Objective C IBAction touchIDAvailable UIButton touchIDAvail
  • 在 nHibernate 关系中使用实体的 Lite 版本?

    在某些情况下 出于性能原因 创建一个实体的轻量级版本 指向同一个表 但映射的列较少 这是一个好主意吗 例如 如果我有一个包含 50 列的联系人表 并且在一些相关实体中 我可能对 FirstName 和 LastName 属性感兴趣 那么创建
  • Swift 中的 import 语句是否有相关成本?

    阅读字符串宣言 我看到一个段落 https github com apple swift blob master docs StringManifesto md batteries included关于避免Foundation不需要的时候导

随机推荐

  • 如何在实时模板中将变量的一个实例大写?

    我正在尝试为 React useState 制作一个模板 const item setItem useState value const state set state useState init end Since item是一样的 只是
  • 找到隐藏元素的“潜在”宽度

    我目前正在延长拉瓦灯插件 http www gmarwaha com blog 2007 08 23 lavalamp for jquery lovers 处理下拉菜单 但我遇到了一个小问题 我需要知道offsetWidth隐藏的元素 现在
  • Vuex 响应式 mapGetters 并传递参数

    我有很多 getter 将参数传递给商店 例如 this store getters getSomeThing this id 我没有找到有关如何最佳使用的建议mapGetters保持反应性 同时传递参数 我发现的一个建议是映射 gette
  • 多 UI 线程 - Winforms

    我想在我的应用程序中创建多个 UI 线程 我模拟了如下场景 我正在单击按钮创建一个新窗口 表单背景 thread namespace WindowsFormsApplication1 public partial class Form1 F
  • 如何在不破坏 JPanel 的默认实现的情况下实现 MouseWheelListener?

    简单地 我有一个JPanel里面一个JScrollPane 正如预期的那样 JScrollPane默认听MouseWheelEvent这样 当滚轮旋转且光标悬停在滚动条上时 滚动效果很好JPanel But在那之后 我刚刚更新了JPanel
  • Asp.Net MVC 5 Owin Twitter Auth 抛出 401 异常

    我已经使用 Owin 中间件设置了 OAuth 身份验证 该中间件基于使用 个人帐户 身份验证启动新 Web 项目时创建的默认项目 我对其进行了一些调整 但 Facebook 和 Google 运行良好 但是 当我单击 twitter 按钮
  • Drupal 7:上传时重命名文件(通过文件字段)

    我正在寻找一种方法来重命名用户通过文件字段上传的文件 例如 使用以下命令重命名用户个人资料照片uniqid 我在 D6 找到了一个很好的解决方案Drupal 6 如何在上传时更改文件名 http www wesjones net home
  • django-tastypie - 如何通过关系实现多对多

    我正在为一个项目开发 API 并且通过 OrderProducts 建立订单 产品关系 如下所示 在目录 models py中 class Product models Model 按顺序 models py class Order mod
  • 寻找一些有趣的 C# 编程问题 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我厌倦了典型的 CRUD 编程类型应用程序 我想解决一些有趣的 不太难的 编程问题 有没有任何网站可以帮助我锻炼大脑 欧拉计划 htt
  • 如何使通用 SSR 的 Angular 应用程序使用 json 文件中的动态配置?

    我的任务是在应用程序启动期间从服务器上的 JSON 文件动态加载 Angular 应用程序的设置 特殊之处在于该应用程序使用 Universal 的服务器渲染 我尝试使用这种方法为浏览器执行此操作 https juristr com blo
  • 谁执行 unicode 标准化以及何时执行?

    根据JavaScript 权威指南 JavaScript 假定它正在解释的源代码已经标准化 并且不会尝试标准化标识符 字符串或正则表达式本身 Unicode 标准定义了所有字符的首选编码 并指定了将文本转换为适合比较的规范形式的规范化过程
  • 如何在 Rails 中将数组分配给 Mysql 列?

    我有一个 PostgreSQL 表 我想在 Rails 应用程序中将其转换为 MySql 最主要的是gateways列不会转换为 数组 列 在 schema rb 中看起来像这样 create table settings force ca
  • 为什么我们不能用右值 volatile int&& 初始化对 const int 的引用?

    我写了下面的例子 include
  • yacc shift-reduce 处理不明确的 lambda 语法

    我正在用 Yacc 用 Go 打包的语言 编写一种玩具语言的语法 由于以下伪问题 我遇到了预期的移位归约冲突 我必须将问题语法提炼为以下内容 start stmt list expr INT IDENT lambda expr 2 lamb
  • 指定不同的公共路径

    我的 Laravel 应用程序在私有文件夹中运行 我需要告诉 Laravel 公共路径是不同的 今天我将 Laravel 应用程序从 4 2 升级到 5 0 但我找不到在哪里指定公共路径因为 paths php 文件在 Laravel 5
  • Python create_task 在运行事件循环中不起作用

    我有一段简单的代码让我发疯了一段时间 我已经发帖了this https stackoverflow com questions 56350166 python event loop does not work properly with s
  • 使用javascript和jquery,用数组结构填充相关的选择框

    使用答案这个问题 https stackoverflow com questions 57522 javascript array with a mix of literals and arrays 我已经能够根据另一个选择框的选择来填充一
  • IntelliJ 下划线反斜杠

    我使用反斜杠作为我正在处理的序列化格式的转义字符 我将它作为常量 但 IntelliJ 强调它并以红色突出显示 悬停时 它不会给出错误消息或任何有关其不喜欢它的原因的信息 这是什么原因以及如何解决 IntelliJ 比我聪明 意识到我在正则
  • 将 python 列表转换为字典

    我正在尝试将我的列表转换为 python 中的字典 我有清单l l a b c d 我想将它转换为字典 d d a d b d c d d 我正在尝试 for i in range 0 len l d i 0 l i 但这行不通 谢谢 保持
  • 即使使用 -Ofast,Swift 的字典也很慢

    我正在使用本质上实现缓存Dictionary在斯威夫特 表现远远低于我的预期 我读过其他一些问题 例如这是关于数组排序的 https stackoverflow com questions 24101718 swift performanc