【问题标题】:Memory usage when converting methods to static methods将方法转换为静态方法时的内存使用情况
【发布时间】:2010-06-25 17:25:57
【问题描述】:

我开始使用 Resharper,它指出了何时可以将方法 设为静态。将几百个方法转换为静态方法会在很长一段时间内增加内存占用吗?

【问题讨论】:

    标签: c# garbage-collection static-methods


    【解决方案1】:

    否 - 更改为静态方法对内存没有影响。

    第一次引用类型时(无论是静态的还是非静态的),都会初始化所有静态成员并运行静态构造函数。

    但是,如果您只是考虑将方法从非静态切换到静态,这不会影响垃圾收集或总内存占用。

    如果您将类成员更改为静态成员,您只需要担心内存占用的变化。在这种情况下,一旦类型被访问,静态字段将保持根,并且不会被 GC 收集。这通常只在必要时进行,并且是有意为之 - 您将成员设为静态是因为您希望它持久存在。

    【讨论】:

    • 内存中是否有存储静态方法的副本?我的假设是,当您引用静态方法时,它会存储在某个地方,然后每个后续引用都会使用该方法的该实例,但我理解这种假设可能是错误的。
    • “方法”,无论是静态方法还是实例方法,当它们被带入进程空间时,都会在内存中加载一次,并由 JIT 编译。静态和非静态之间的方法使用确实没有区别。关注静态方法是否适合您的特定情况 - 并使用它来确定方法应该是静态方法还是实例方法。
    • 对内存的影响非常小 - 因为会生成额外的代码来将“this”指针传递给不使用它的方法。
    • @Qwertie:这种影响只是在方法调用期间改变了堆栈的内存需求,但不会改变对内存存储的“长期”影响。话虽如此,堆栈是为每个线程预先分配的,因此“真正的”内存需求不会改变。 ;)
    【解决方案2】:

    从 JIT 编译器的角度来看,静态方法和实例方法没有区别。它们的机器代码非常相似,存储在同一种堆中。唯一的区别是实例方法有一个额外的参数。

    调用方法时需要传递额外的参数。这可能会花费额外的机器代码指令,但不会那么频繁。 CPU 寄存器 (ECX) 通常已经具有正确的值。如果实例方法在 x86 上具有多个参数或在 x64 上具有三个以上参数,则存在差异,则必须在堆栈上而不是通过 CPU 寄存器传递额外的参数。一条额外的指令。

    最坏的情况是,您看到的时间不到一纳秒。这将很难衡量,这是微优化的常见问题。

    【讨论】:

    • 这可能超出了原始问题的范围,但是当调用静态或非静态方法时,堆上存储了什么?它只是方法本身,还是包含该方法的类的实例,或者完全是其他东西?垃圾收集是否曾经收集过这些内存?
    • 在方法调用期间没有任何内容存储在堆上。参数通过 CPU 寄存器和堆栈传递。什么都不需要收集。 Petzold 的书“代码”可能会让您感兴趣。
    • 好吧,这很有意义。所以真的,将我的方法从非静态转换为静态的唯一原因是在没有类实例化的情况下访问它们?感谢您的推荐。
    • 之所以编写静态方法是因为它不需要引用任何实例成员。不要疯狂地“转换”应该是实例方法的方法,这几乎不值得付出代价。如果您有性能问题,请先测量。
    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2011-01-21
    • 2013-03-12
    • 2023-01-05
    • 2011-11-17
    • 1970-01-01
    • 2020-11-13
    • 2011-05-16
    相关资源
    最近更新 更多