- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
所以我在读this article关于尝试从 Python 解释器中删除全局解释器锁 (GIL) 以提高多线程性能并看到一些有趣的东西。
事实证明,删除 GIL 实际上使事情变得更糟的地方之一是内存管理:
With free-threading, reference counting operations lose their thread-safety. Thus, the patch introduces a global reference-counting mutex lock along with atomic operations for updating the count. On Unix, locking is implemented using a standard pthread_mutex_t lock (wrapped inside a PyMutex structure) and the following functions...
...On Unix, it must be emphasized that simple reference count manipulation has been replaced by no fewer than three function calls, plus the overhead of the actual locking. It's far more expensive...
...Clearly fine-grained locking of reference counts is the major culprit behind the poor performance, but even if you take away the locking, the reference counting performance is still very sensitive to any kind of extra overhead (e.g., function call, etc.). In this case, the performance is still about twice as slow as Python with the GIL.
及以后:
Reference counting is a really lousy memory-management technique for free-threading. This was already widely known, but the performance numbers put a more concrete figure on it. This will definitely be the most challenging issue for anyone attempting a GIL removal patch.
所以问题是,如果引用计数对于线程来说如此糟糕,那么 Objective-C 是如何做到的呢?我编写过多线程 Objective-C 应用程序,并没有注意到内存管理的开销很大。他们在做别的事吗?像某种按对象锁而不是全局锁? Objective-C 的引用计数实际上在技术上对线程不安全吗?我不是并发专家,无法真正推测很多,但我很想知道。
最佳答案
存在开销,并且在极少数情况下(例如,微基准测试;),无论是否进行了优化(其中有很多),它都可能很重要。不过,正常情况针对对象引用计数的非竞争操作进行了优化。
So the question is, if reference counting is so lousy for threading, how does Objective-C do it?
有多个锁在起作用,实际上,对任何给定对象的保留/释放会为该对象选择一个随机锁(但始终是相同的锁)。因此,减少了锁争用,同时不需要每个对象一个锁。
(以及 Catfish_man 所说的;一些类将实现自己的引用计数方案以使用特定于类的锁定原语来避免争用和/或针对其特定需求进行优化。)
实现细节比较复杂。
Is Objectice-C's reference counting actually technically unsafe with threads?
不——它在线程方面是安全的。
实际上,与其他操作相比,典型代码很少会调用retain
和release
。因此,即使这些代码路径上存在大量开销,它也会分摊到应用程序中的所有其他操作(相比之下,将像素推送到屏幕的开销真的)。
如果一个对象跨线程共享(通常是个坏主意),那么保护数据访问和操作的锁定开销通常会远远大于保留/释放开销,因为保留/释放的频率不高。
就 Python 的 GIL 开销而言,我敢打赌它更多地与引用计数作为正常解释器操作的一部分递增和递减的频率有关。
关于objective-c - Apple 的 Objective-C 运行时如何在不降低性能的情况下进行多线程引用计数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13942226/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!