静态类是否会导致多核系统出现性能问题?

时间:2008-12-12 12:39:25

标签: performance language-agnostic static class

前几天,我的一位同事声称使用静态类会导致多核系统出现性能问题,因为静态实例无法在处理器缓存之间共享。是对的吗?是否有一些基准来证明这种说法?这个陈述是在.Net开发(与C#)相关讨论的背景下做出的,但听起来像是一个语言和环境无关的问题。

感谢您的评论。

8 个答案:

答案 0 :(得分:14)

我会推动您的同事获取数据或至少引用。

问题是,如果您有共享数据,那么您就拥有了共享数据。无论是通过静态类,单例,还是其他方式暴露,都不是非常重要。如果您首先不需要共享数据,我希望您不会有静态类。

除此之外,在任何给定的应用程序中,静态类中的共享数据的处理器缓存可能存在更大的瓶颈。

与以往一样,首先编写最明智,最易读,最易维护的代码 - 如果遇到性能瓶颈并采取相应措施,请确定代码。

答案 1 :(得分:3)

“[a]静态实例无法在处理器缓存之间共享。是吗?”

这句话对我来说没什么意义。每个处理器的专用缓存的要点是它包含一小块内存的私有副本,因此如果处理器正在执行一些只需要访问该特定内存区域的算法,那么它就不必继续回来访问外部存储器。如果我们讨论静态类中的静态字段,那些字段的内存可能都适合连续的内存块,而后者又适合单个处理器(或内核)的专用缓存。但是它们每个都有自己的缓存副本 - 它不是“共享”的。这就是缓存的重点。

如果算法的工作集大于缓存,那么它将击败该缓存。这意味着当算法运行时,它会重复使处理器从外部存储器中提取数据,因为所有必需的部分都不会立即适合缓存。但这是一个普遍的问题,不适用于静态类。

我想知道你的同事实际上是在谈论性能,而是在多个线程正在读/写相同数据时是否需要应用正确的锁定?

答案 2 :(得分:3)

如果多个线程正在写入到该数据,则会有缓存抖动(一个CPU缓存上的写入会使其他CPU的缓存无效)。你的朋友技术上是正确的,但很有可能它不是你的主要瓶颈,所以没关系。

如果多个线程正在读取数据,那么您的朋友就会出现问题。

答案 3 :(得分:2)

如果您不使用任何类型的锁或同步,则静态与非静态不会对您的性能产​​生任何影响。

如果您正在使用同步,那么如果所有线程都需要获取相同的锁,则可能会遇到问题,但这只是静态的副作用,而不是方法静态的直接结果。 / p>

答案 4 :(得分:2)

在任何“虚拟机”控制语言(.NET,Java等)中,此控件可能会委托给底层操作系统,并可能进一步下载到BIOS和其他调度控件。话虽如此,在.NET和Java这两个大问题中,静态与非静态是内存问题,而不是CPU问题。

重新讨论saua的观点,对CPU的影响来自同步和线程控制,而不是对静态信息的访问。

CPU缓存管理的问题不仅限于静态方法。一次只能有一个CPU可以更新任何内存地址。虚拟机中的对象,特别是对象中的字段,是指向所述内存地址的指针。因此,即使我有一个可变对象Foo,在Foo上调用setBar(true)一次只允许在一个CPU上。

所有这一切,.NET和Java的关键在于你不应该把时间花在讨论这些问题上,直到你能证明你有问题并且我怀疑你会这样做。

答案 5 :(得分:1)

  1. 如果您在线程之间共享可变数据,则需要锁定或无锁算法(很少可用,有时很难使用)。
    • 拥有少量广泛使用的锁定仲裁资源可能会让您陷入瓶颈。
    • 静态数据类似于单实例资源。
  2. 因此:

    • 如果有很多线程访问静态数据,而你使用锁来进行仲裁,那么你的线程就会争取访问权。

    在设计高度多线程的应用程序时,请尝试使用许多细粒度的锁。分割你的数据,以便一个线程可以抓取一个并运行它,希望没有其他线程需要等待它,因为他们忙于自己的数据。

答案 6 :(得分:1)

x86架构实现了缓存侦听,以便在写入时保持数据缓存同步,如果它们碰巧缓存相同的东西......并非所有架构都在硬件中执行此操作,有些架构依赖于软件来确保案例永远不会发生。 / p>

答案 7 :(得分:0)

即使这是真的,我怀疑你有很多更好的方法来提高性能。当它将静态更改为实例时,对于处理器缓存,你会知道你真的在推动它的发展。