同一应用程序中的多个静态变量范围?

Posted

技术标签:

【中文标题】同一应用程序中的多个静态变量范围?【英文标题】:Multiple static variable scopes within same application? 【发布时间】:2011-10-01 16:01:07 【问题描述】:

在同一个应用程序中设置多个静态范围的最佳方法是什么? 我有一些结构可以作为访问数组的包装器。

这是一个例子:

class FooClass
   static int[] BarArray;


struct FooStruct
    public int BarArrayIndex;

    public int BarArrayValue  
      get  return FooClass.BarArray[BarArrayIndex];  
      set  FooClass.BarArray[BarArrayIndex] = value; 
    

出于性能原因,我不想在 FooStruct 的每个实例中存储对 BarArray 的引用,因此我将数组声明为静态的。 但是,将来我可能必须同时使用多个不同的 BarArray(其中结构的不同实例应该指向不同的数组)。有没有办法实现这一点,而不必在结构的每个实例中存储额外的引用,也不使用静态变量? 如果不是,那么使用多个静态实例同时让整个应用程序对最终用户感觉是“一个应用程序”的最佳方式是什么?

【问题讨论】:

“出于性能原因,我不想在每个 FooStruct 实例中存储对 BarArray 的引用”——过早的微优化。 我非常怀疑额外的引用是否会对性能产生任何影响。 【参考方案1】:

您似乎认为持有对数组的引用意味着复制数组.. 即您的结构的每个实例都将包含数组的副本?不是这种情况。所有结构将包含对数组的引用......一个指针。内存中只存在一个数组实例。我不确定这是否会为您带来任何性能积分。

【讨论】:

只是出于好奇......我是否认为在 64 位机器上对对象的引用(指针而不是实例)会占用 64 位内存?所以这一切都是为了节省 8 个字节......在一台内存以 Gb 为单位的机器中。我真的不会为此烦恼。 不,我认为它不会保存数组的副本,但它至少会保存另外 4 个字节的数据,我想避免这种情况。可以同时创建和复制数百万个这样的结构。 对于 1m 个对象,每个引用 8 个字节,我们说的是 8mb 的 RAM ...顶部。我什至怀疑微软在构建框架时对内存使用的效率是否如此之高?请问这个软件要在什么样的机器上运行?我能想到的任何现代电脑都不需要这种内存效率。您可以尝试使用/不使用静态对象进行快速测试并测量内存占用。您是否真正衡量过您要优化的性能问题? 不仅仅是内存。每次我创建一个新实例或复制它(将其传递给方法等)时,它也会增加一些 cpu 时间开销。这是我想尽量减少的主要事情。我实际上正在重写我之前编写的应用程序,因为它运行速度太慢,现在我想从基础上优化某些东西,只要它们不会导致严重的设计问题。尝试查看是否可以在不牺牲可扩展性的情况下消除额外的数组引用。别忘了,额外的引用可以使我的结构体的大小增加一倍或三倍。 回答你原来的问题......你不能。静态意味着内存中的一个实例和一个指向它的全局指针。它不可能替代实例。 Feraref 走在正确的轨道上.. 我能看到的唯一方法是将其实现为单例而不是静态,并使用 IOC 容器注入实例。使用 IOC 容器将需要比您尝试保存的内存更多的内存,因此我认为您拥有的最好的情况就是为引用获取内存。【参考方案2】:

你不能。静态的重点是在整个应用程序上拥有一个实例。

改为查看Dependency Injection。它应该可以完美地满足您的用例,并且是处理此类问题的首选方式。

【讨论】:

我看不到依赖注入如何完美地满足这个用例(关于性能)。可以给我看看吗?【参考方案3】:

这不仅仅是记忆。每次我创建一个新实例或复制它 (将其传递给方法等)它也会增加一些 CPU 时间开销。 这是我想最小化的主要内容

然后让它们成为类对象。然后你只需要传递一个引用,你就可以向数组添加一个引用而不会受到惩罚。 (不,在堆上使用 1M 小对象不是性能问题)。

但我严重怀疑复制小结构是否被分析器挑出来。听起来你在猜测瓶颈在哪里。

【讨论】:

如果我让它们成为类对象,这会使性能变得更糟。如果我可以摆脱只保存一个整数(它在数组中的索引)的结构,那么它只有 4 个字节。你们可以参考我原来的问题吗?我不想分享整个问题,因为它需要一个更大的描述,而我实际提出的问题代表了它的本质。我有我的理由为什么我需要解决这个确切的问题。如果我想知道如何在不使用结构的情况下解决它,我会问的。 “我们的人”在这里会看到很多不成熟和愚蠢的优化问题。只是要求找出你的是否有任何物质。到目前为止,没有一个被检测到。但是您的基本问题已被多次回答,答案是“否”。 很好,很抱歉看到所有这些与我的问题无关的答案有点生气。下次我将从一个更好的指定开始。无论如何,谢谢你的回答。我只是以某种方式认为有一些常见的方法可以消除这样的引用。但是,我确实收到了一个可能导致解决方案的答案。【参考方案4】:
static class FooClass
    private static int[][] barArrays;

    public static int[] getBarArray(int instanceIndex)
    
        return barArrays[instanceIndex];
    


struct FooStruct
    private int instanceIndex;
    public int BarArrayIndex;

    public int BarArrayValue  
        get  return FooClass.getBarArray[instanceIndex][BarArrayIndex];  
        set  FooClass.getBarArray[instanceIndex][BarArrayIndex] = value; 
    

这是单例模式的推广。

顺便说一句,每个 FooStruct 实例保留一个通用 FooClass 实例的性能损失绝对是微不足道的。

【讨论】:

尽管我们都对可能的性能增益与代码复杂性和可读性存有疑问……这对于可以交换的静态数组的原始问题来说是一个非常巧妙的解决方案。很酷的答案的荣誉:) 这有什么用?持有一个新的整数值 instanceIndex 与持有对 barArray 的引用具有相同的性能损失,它只会降低代码的可用性。【参考方案5】:

此时你能做的最好的事情就是给 FooClass 添加一个工厂方法,负责返回一个BarArray 的实例。

class FooClass 
   int[] GetBarArray() 
   

现在,实现这个方法来返回一个静态对象。如果将来您决定更改创建数组的策略,您只需重新实现工厂方法。

【讨论】:

【参考方案6】:

如果您只想拥有多个静态变量,请为每个上下文使用一个新的 AppDomain。 但我不确定这是否适合您的问题(请参阅其他答案)。

编辑: 教程和帮助http://msdn.microsoft.com/en-us/library/system.appdomain.aspxhttp://www.beansoftware.com/NET-Tutorials/Application-Domain.aspxI don't understand Application Domains

【讨论】:

能否请您指出我可以看到如何在应用程序中创建新 AppDomain 的地方?

以上是关于同一应用程序中的多个静态变量范围?的主要内容,如果未能解决你的问题,请参考以下文章

同一个包,同一个类中,成员变量与成员方法的调用!

局部变量,实例变量,静态变量

静态对象在多个正在运行的应用程序中是同一个对象吗?

在同一个C语言程序项目中,其它.c文件可以访问另一个.c文件中的静态变量吗?

java中static静态变量大小

如何在机器级别或内存级别在编译器中实现变量范围