任何使用软件事务内存的实际经验? [关闭]
Posted
技术标签:
【中文标题】任何使用软件事务内存的实际经验? [关闭]【英文标题】:Any Real-World Experience Using Software Transactional Memory? [closed] 【发布时间】:2010-09-17 14:35:38 【问题描述】:似乎最近人们对 STM(软件事务内存)框架和语言扩展的兴趣越来越高。 Clojure 尤其具有出色的实现,它使用 MVCC (multi-version concurrency control) 而不是滚动提交日志。 GHC Haskell 也有an extremely elegant STM monad,它也允许交易组合。最后,为了稍微吹嘘一下我自己的号角,我最近实现了一个STM framework for Scala,它静态地强制执行引用限制。
所有这些都是有趣的实验,但它们似乎仅限于那个领域(实验)。所以我的问题是:你们有没有人在现实世界中看到或使用过 STM?如果是这样,为什么?它带来了什么样的好处?性能呢? (在这一点上似乎有很多相互矛盾的信息)您会再次使用 STM 还是更喜欢使用其他一些并发抽象,例如 actor?
【问题讨论】:
如果你在clojure列表上问这个,你会得到很多回应。我相信 clojure 是由 Rich Hickey 实际拥有的需求驱动的,它对 STM 的支持是因为他需要它,而不是作为实验。 哦,我相信我会的!但我对 STM 在 Clojure 领域之外的用途更感兴趣。毕竟,这不是一个新想法,应该有有人觉得它有用。 作为旁注,微软似乎在 .NET 中对 STM 进行了一些正在进行的实验 - 足以发布一个有效的实现:msdn.microsoft.com/en-us/devlabs/ee334183.aspx - 现在我怀疑这是否正在完成只是为了好玩,与 .NET 集成肯定引入了一个非常实用的角度,我倾向于将这甚至被认真考虑为一项成熟到足以“生产”的技术。 微软的实验以失败告终。 infoq.com/news/2010/05/STM-Dropped 【参考方案1】:我在 Haskell(名为 conjure)中参与了 BitTorrent 客户端的业余爱好者开发。它大量使用 STM 来协调不同的线程(每个节点 1 个 + 1 个用于存储管理 + 1 个用于整体管理)。
好处:更少的锁,可读的代码。
速度不是问题,至少不是因为使用了 STM。
希望对你有帮助
【讨论】:
【参考方案2】:在 Galois(在 Haskell 中),我们经常将它用于高并发应用程序。它有效,在 Haskell 世界中广泛使用,并且不会死锁(当然你可能有太多的争用)。有时我们会重写一些东西以使用 MVar,如果我们的设计正确的话——因为它们更快。
只需使用它。这没什么大不了的。就我而言,Haskell 中的 STM 已“解决”。没有进一步的工作要做。所以我们使用它。
【讨论】:
【参考方案3】:文章“Software Transactional Memory: Why is it Only a Research Toy?”(Călin Caşcaval 等人,Communications of the ACM,2008 年 11 月) 没有看到 Haskell 的实现,这是一个很大的遗漏。正如文章所指出的那样,STM 的问题在于,实现必须在使所有变量访问都是事务性的,除非编译器可以证明它们是安全的(这会降低性能),还是让程序员指示哪些是事务性的(这会降低简单性)和可靠性)。然而,Haskell 实现使用 Haskell 的纯度来避免使大多数变量使用事务性的需要,而类型系统提供了一个简单的模型以及对事务性变异操作的有效执行。因此,Haskell 程序可以将 STM 用于真正在线程之间共享的变量,同时保证非事务性内存使用是安全的。
【讨论】:
论文“软件事务内存:为什么它只是一个研究玩具?”由愤怒的 Bryan Cantrill 在 ACM 队列中介绍:Concurrency's Shysters,2008 年 11 月。“对于第一篇文章,我们有幸找到 Calin Cascaval 及其同事,他们最终写了一篇关于 STM 的必读文章在 11 月的 CACM 上。他们的结论是不可避免的:STM 是一条狗。(或者像 Cascaval 等人更巧妙地说:“根据我们的结果,我们认为 STM 的道路非常具有挑战性。”) Muh锁! 最终就像将数据库拉入您的编程语言(或使编程语言成为 PL/x 脚本语言)。如果您继续使用公共数据库缓存(即使用可变状态),那么这个好主意就会被残忍地扼杀。 Jonathan Allen:我们注意到的第一个例子是一个 trx 从链表中删除一个节点,而另一个 trx 正在遍历同一个链表。如果前一个线程仅仅因为将它从列表中删除而认为它“拥有”被删除的元素,那么当它的状态继续变化时,有人会感到失望。?【参考方案4】:我们factis research GmbH 在生产中使用带有 GHC 的 Haskell STM。我们的服务器从临床“数据服务器”接收有关新的和修改的“对象”的消息流,它动态转换此事件流(通过生成新对象、修改对象、聚合事物等)并计算其中哪些是新的对象应同步到连接的 iPad。它还接收来自 iPad 的表单输入,这些输入经过处理、与“主流”合并并同步到其他 iPad。我们将 STM 用于需要在线程之间共享的所有通道和可变数据结构。 Haskell 中的线程非常轻量级,因此我们可以拥有很多线程而不会影响性能(目前每个 iPad 连接 5 个)。构建大型应用程序始终是一个挑战,有很多经验教训要学习,但我们在 STM 上从来没有遇到过任何问题。它总是像你天真地期望的那样工作。我们必须进行一些认真的性能调整,但 STM 从来都不是问题。 (80% 的时间我们试图减少短期分配和整体内存使用。)
STM 是 Haskell 和 GHC 运行时真正大放异彩的一个领域。这不仅仅是一个实验,也不仅仅是玩具程序。
我们正在 Scala 中构建临床系统的不同组件,并且到目前为止一直在使用 Actors,但我们确实缺少 STM。如果有人对在生产中使用 Scala STM 实现之一有什么经验,我很乐意听取您的意见。 :-)
【讨论】:
【参考方案5】:我们已经在我们自己用 C 语言实现的 STM 之上实现了整个 system(内存数据库和运行时)。在此之前,我们有一些基于日志和锁的机制来处理并发,但这是一个痛苦维持。我们对 STM 非常满意,因为我们可以以同样的方式对待每个操作。几乎所有的锁都可以拆除。我们现在几乎将 STM 用于任何大小的任何东西,我们甚至在顶部实现了内存管理器。
性能很好,但为了加快速度,我们现在与苏黎世联邦理工学院合作开发了一个自定义 operating system。系统原生支持事务内存。
但 STM 也带来了一些挑战。尤其是较大的交易和热点会导致不必要的交易冲突。例如,如果两个事务将一个项目放入一个链表中,则会发生不必要的冲突,而使用无锁数据结构可以避免这种冲突。
【讨论】:
【参考方案6】:我目前在一些 PGAS 系统研究中使用 Akka。 Akka 是一个 Scala 库,用于使用 Actors、STM 和内置容错功能开发可扩展的并发系统,这些功能模仿 Erlang 的“让它失败/崩溃/陨石坑/ROFL”哲学。 Akka 的 STM 实现据说是围绕 Clojure 的 STM 实现的 Scala 端口构建的。 Akka 的 STM 模块的概述可以在 here 找到。
【讨论】:
以上是关于任何使用软件事务内存的实际经验? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
STM 软件事务内存——本质是为提高并发,通过事务来管理内存的读写访问以避免锁的使用