Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的内存管理#_C# - Fatal编程技术网

C# C语言中的内存管理#

C# C语言中的内存管理#,c#,C#,下午好 我有一些文本文件,其中包含通过分析报纸文章语料库收集的(2克,计数)对列表,当我启动我正在开发的给定应用程序时,需要将这些文本文件加载到内存中。为了存储这些对,我使用如下结构: private static Dictionary<String, Int64>[] ListaDigramas = new Dictionary<String, Int64>[27]; private static Dictionary[]ListaDigramas=新字典[27];

下午好

我有一些文本文件,其中包含通过分析报纸文章语料库收集的(2克,计数)对列表,当我启动我正在开发的给定应用程序时,需要将这些文本文件加载到内存中。为了存储这些对,我使用如下结构:

private static Dictionary<String, Int64>[] ListaDigramas = new Dictionary<String, Int64>[27];
private static Dictionary[]ListaDigramas=新字典[27];
拥有一系列字典的想法是由于效率问题,因为我在某处读到过一本长字典对性能有负面影响。也就是说,每2克进入对应于它的第一个字符的ASCII码减去97的字典(如果第一个字符不是“a”到“z”范围内的字符,则为26)

当我将(2-gram,count)对加载到内存中时,应用程序总共需要800Mb的RAM,并且一直保持这种状态,直到我使用名为memory Cleaner的程序释放内存。在这之后,程序占用的内存将下降到7Mb-100Mb的范围,而不会丢失功能(我认为)

有什么方法可以这样释放内存,但不使用外部应用程序?我尝试使用
GC.Collect()
,但在这种情况下不起作用


非常感谢。

您使用的是一个静态字段,因此一旦加载它,它就不会被垃圾收集,因此除非您调用此词典上的
.Clear()
方法,否则它可能不会被垃圾收集。

我不知道内存清理器如何工作的细节,但考虑到不太可能知道程序内存分配的内部工作原理,它所能做的最好的可能就是将页面交换到磁盘上,从而减少程序的内存使用


除非您实际拥有不再使用的对象,否则垃圾收集不会有任何帮助。如果您正在使用字典(GC认为您正在使用字典,因为它是一个静态字段),那么字典中的所有对象都被认为正在使用,并且必须属于程序的活动内存。这是没有办法的。

对于我来说,像这样的实用程序是如何在某人的机器上运行的,这是相当神秘的。它们所做的只是调用EmptyWorkingSet()。也许它在Taskmgr.exe中看起来不错,但在其他方面,它只是让硬盘不必要地忙碌的一种方式。通过最小化应用程序的主窗口,您将得到完全相同的结果。

非常感谢您提供的所有答案。数据实际上需要在应用程序的整个运行期间加载,因此根据您的回答,我认为没有更好的方法可以做。。。我也许可以尝试一个外部数据库,但由于我已经需要同时处理另外两个数据库,我认为这不是一个好主意


您是否认为可以同时处理三个数据库而不损失性能?

您看到的是应用程序的总使用率。这是800MB,将保持这种状态。正如评论所说,内存清理器使应用程序看起来使用更少的内存。您可以尝试在运行内存清理器后访问字典中的所有值。您将看到内存使用率再次上升(从交换中读取)

您可能希望的是不要将所有这些数据加载到内存中。有没有一种方法可以让你用算法得到同样的结果


或者,如果您实际上是在这里存储信息,那么这可能是最好的选择,您可以使用数据库。如果使用像SQLExpress这样的普通数据库很麻烦,您可以随时使用。

如果您正确地处理了应用程序资源,那么实际使用的内存可能不是您看到的(如果通过任务管理器进行验证)

垃圾收集器将在最佳时间释放未使用的内存。通常强制收集也不是一个好主意…看到这个了吗


“数据实际上需要在应用程序的整个运行期间加载”-为什么?

关于我唯一能想到的另一个想法,如果你真的想降低内存使用率,那就是将字典存储在一个流中并压缩它。要考虑的因素是你访问/膨胀这些数据的频率,以及数据的可压缩性。来自报纸文章的文本压缩效果会非常好,而且性能的影响可能比你想象的要小

使用像SharpZipLib()这样的开源库,您的代码看起来像:

MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();

formatter.Serialize(stream, ListaDigramas);
byte[] dictBytes = stream.ToArray();

Stream zipStream = new DeflaterOutputStream(new MemoryStream());
zipStream.Write(dictBytes, 0, dictBytes.Length);
充气需要一个
InflaterInputStream
和一个循环来将流分块充气,但这相当简单

你必须玩这个应用程序,看看性能是否可以接受。当然,要记住,当你将字典充气使用时,你仍然需要足够的内存来保存它(除非有人有聪明的主意在压缩状态下处理对象)

不过,老实说,保持它在内存中的原样并让Windows将其交换到页面文件可能是最好/最快的选择

编辑
我从未尝试过,但您可能能够直接序列化到压缩流,这意味着压缩开销最小(您仍然有序列化开销):


你能添加你用来加载字典的代码吗?内存清理器只需将你应用程序的所有内存移到虚拟内存(也称为交换)。你要加载多少内容?为什么字符串映射到值?你是如何使用这些东西的?与这些对相对应的文本文件在磁盘上总共占用191Mb的空间,但并不是所有的对都被加载(只有那些频率至少为50的对)。如果你担心内存使用,也许你可以使用内存映射文件。这当然不像使用字典那么简单,所以也许数据库(可以嵌入SQLite)更合适。。。OP:如果你最小化主窗口会发生什么?事实上,很多都是w
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();

Stream zipStream = new DeflaterOutputStream(new MemoryStream());

formatter.Serialize(zipStream, ListaDigramas);