繁体   English   中英

内存中的大型数据集 - .NET Framework和C#

[英]Large dataset in memory - .NET Framework and C#

我有一个DLL项目,它使我的应用程序中使用的所有显示字符串的单例。 问题是我需要在许多独立运行的应用程序中引用此DLL。

据我所知,如果我在所有独立运行的应用程序中引用DLL项目,它们都会将DLL加载到内存中并创建它们可以引用的单个单例,但这是我想要避免的冗余。

有没有办法可以将这个单例的一个实例保存在内存中并从所有独立项目中引用它?

我知道我可能听起来很愚蠢,而且这种装载可能根本不会发生,但我现在一直在搜索大约一个小时:)

我使用.NET框架和C#作为目标语言。

通常,不同的进程具有不同的地址空间。 由于DLL文件通常被加载到进程地址空间中,因此有必要编写一些特殊代码来实现进程之间的数据共享。 通常,这是使用Windows API完成的,例如,借助内存映射文件。 您可以在以下位置了解更多信息:

在两个进程之间共享内存(C,Windows)

使用Windows API并不错,但它在某种程度上与.NET Framework理念相矛盾。 我认为当单个服务器可以与不同的客户端一起工作并将所需的数据传递给它们时,最好创建一个客户端 - 服务器体系结构。 这可以使用例如RemotingWCF来完成。

在真正成为问题之前,我不会为内存消耗而烦恼。 我们可以做一些简单的数学运算:2 ^ 3(8)个应用程序中的2 ^ 13(8192)个字符串是2 ^ 16个字符串,如果一个字符串的平均大小为2 ^ 8(256)个字符,则所有字节的总字节数应用程序是2 * 2^24 (32 MiB)。 即使字符串的数量乘以10,这也不会造成任何问题。

其他解决方案所需的工作量将使其在当前阶段不可行。 如果所有应用程序都使用大多数共享字符串,那么常见的字符串服务也没有任何好处。 只有当一小部分字符串真正由它们共享时,它才能提供好处。

使用远程处理,您必须确保单个实例仅在一个位置初始化,并且您必须通过接口访问它。 您很可能想要创建一个本地单例实例,该实例从远程实例查询字符串。 如果您继续使用旧的单例实现,直到需要其他解决方案,此后也可以实现此解决方案。

如果使用taskmanager来跟踪内存使用情况,那么单例类中应该有一个非常大的字符串。

public static Strings {
    private readonly string MemoryUsageTest;

    static Strings() {
#if DEBUG
        int size = 104000000;
        var text = "abcdefghijklmnopqrstuvwxyz";
        var sb = new StringBuilder(size);

        for (int i = 0; i < size / text.Length; ++i) {
            sb.Append(text);
        }

        MemoryUsageTest = sb.ToString();
#endif
    }
}

我不太确定远程处理在任何时候都是一个不错的选择。 无论如何,如果我们假设它是一个很好的替代方案,我建议当前的实现应该使用实现接口的单例类。 这将使远程实例的使用变得更加容易。

public interface IStrings {
    string HelloWorld { get; }
}

public sealed class LocalStringService : IStrings {
    internal LocalStringService() { }

    string IStrings.HelloWorld {
        get { return "Hello World!"; }
    }
}

public static class StringService {
    private static readonly IStrings SingletonInstance = new LocalStringService();

    // If empty static constructor does not make any sense, read this:
    // http://csharpindepth.com/Articles/General/Beforefieldinit.aspx
    static StringService() { }

    public static IStrings Instance {
        get { return SingletonInstance; }
    }
}

现在,如果要创建此远程,则只需要将LocalStringService重命名为RemoteStringService ,使其继承MarshalByRefObj并更改StringService以创建它的远程实例。 此外, RemoteStringService应位于另一个程序集中,以便它不会与其他类一起加载到内存中。

不过,我怀疑这会给你带来任何好处。

使用的字符串常量很可能是实体。 调用string.IsInterned静态函数来查看特定字符串。 如果是这种情况,他们不会占用过多的内存,因为每个字符串都在CLR实习池中。

IsInterned

在此DLL文件上创建一个服务包装器,然后从其他应用程序调用该服务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM