C# 序列化/反序列化后使用的ram大小异常增加

C# 序列化/反序列化后使用的ram大小异常增加,c#,memory,serialization,C#,Memory,Serialization,我使用以下方法在序列化后将应用程序数据保存到文件中,并在反序列化(en/解密)后从此文件加载数据 若应用程序中并没有数据,我会向其中添加大约100MB的数据(基于任务管理器)并保存它。加载数据后,任务管理器显示应用程序数据约为200-400 MB 为了使用此方法将应用程序类封装为一个类,我使用了如下类: public class BigClass { public ClassA classA; public ClassB classB; public BigClass

我使用以下方法在序列化后将应用程序数据保存到文件中,并在反序列化(en/解密)后从此文件加载数据

若应用程序中并没有数据,我会向其中添加大约100MB的数据(基于任务管理器)并保存它。加载数据后,任务管理器显示应用程序数据约为200-400 MB

为了使用此方法将应用程序类封装为一个类,我使用了如下类:

public class BigClass
{
    public  ClassA classA;
    public ClassB classB;

    public BigClass(ClassA a, ClassB b)
    {
        classA = a;
        classB = b;
    }
}
ClassA
ClassB
(应保存/加载的类)中的每一个都类似于:

public class ClassA
{
    List<ClassASub> list = new List<ClassASub>();

    //some variables...

    //some methodes

    private class ClassASub
    {
        int intValue;
        long longValue;
        string stringValue;
        Image image;

        //some simple methodes....
    }
}
公共类ClassA
{
列表=新列表();
//一些变量。。。
//一些方法
私有类
{
int值;
长期价值;
字符串字符串值;
图像;
//一些简单的方法。。。。
}
}

我不谈论序列化/反序列化过程中使用的RAM的大小。在那之后,我会谈到使用过的RAM,那时应该只存在应用程序数据。

您正在将数据作为数组加载到内存中(
codedClass
)。根据您的指示,这个数组大概在100MB左右,这足以确保在大型对象堆上分配它

现在:GC旨在优化您的整体系统性能;出于多种原因,它的设计目的不是不断主动回收内存:

  • 如果您的系统中有大量的空闲内存(您没有内存压力),并且没有特定的收集需求,那么这是不必要的开销
  • 有些数据的收集成本比其他数据高;其中最昂贵的是大型对象堆,因此它位于队列的后面;首先释放其他内存
  • 即使数据是免费的,将这些页面发布回操作系统也未必有利;进程可以有效地决定保留它们,以避免不断地向操作系统请求内存并将其返还
在您的例子中,您可以尝试使用
System.GC
上的方法强制运行集合,但我认为真正的目标是不分配那些大数组。如果您可以做任何事情来移动到基于
流的
模型,而不是基于数组的模型,那将是很好的。这可能意味着显著更改
SpecialCodeDecoder

关键点:一个数组的上限大小硬一个硬帽;您不能将当前实现扩展到2GB以上(即使启用了

此外,我怀疑
BinaryFormatter
会让事情变得更糟——几乎总是这样。存在其他更高效的陈旧序列化程序。减少序列化的大小将是一个可供选择的选项,而不是-或者与移动到Suth的模型相结合。 另外:您可以尝试在加密的有效负载内使用压缩技术(
GZipStream
deflatesttream
,等等)。您不应尝试压缩加密数据-您需要确保顺序为:

Serialize -> Compress -> Encrypt -> (storage) -> Decrypt -> Decompress -> Deserialize

序列化和压缩阶段已经与流完全兼容。如果你能使加密层与流兼容,你就是赢家了。

你创建的类包含大量数据(例如a类、B类、BigClass)。 每当您创建和使用这样的类来保存许多数据(特别是值类型)时,您必须告诉运行时在不再需要它们时销毁(或处置)它们。 这称为“Dispose模式”,您可以在此处了解更多信息:

有些.net类内置了Dispose()方法,因此,net垃圾收集器(GC)知道何时将它们从内存中清除。但不是所有的。 对于那些拥有Dispose()并实现IDisposable接口的用户,您可以使用“Using”语句在任务完成后自动处理它们(您在代码中使用了一些Using语句,但不是在所有必需的位置)

简单的回答是:序列化完成后,数据仍保留在内存中。让你的类成为一次性的,当你不需要它们的时候就把它们处理掉


[这个问题对您很有帮助:

我建议您使用陈雷蒙的这篇博文:我在列表中看到您的类A中有一个图像属性,一旦您处理完您的对象,它应该被处理:-)♦ 谢谢你的回答。但当我删除一些数据时,它会导致使用的内存减少(基于任务管理器)。例如,加载后,如果删除一半的数据,使用的ram将变成大约一半。这难道不意味着问题在其他地方,每个班级的人数都在增加吗?您所说的是正确的,但在结束加载过程后,我可以看到分配的空间已释放。或者我认为错了,这并不意味着我所想的?@学生,我认为这需要比我在这里提供的更多的专门调查来给出结论性的答案,♦ 谢谢你的回答和时间。我应该更多地测试和搜索。如果我找到一个好答案,我会把它贴在这里
Serialize -> Compress -> Encrypt -> (storage) -> Decrypt -> Decompress -> Deserialize