我的问题可能听起来有些模糊。但我想知道的是List<>
缓冲区的维护位置。
我有一个列表List<MyClass>
,我将从无限循环中添加项目。但Windows服务(我在其中创建List)的RAM消耗从未超过17 MB。事实上,即使我继续向列表中添加项目,它也会徘徊在15-16MB之间。
我正在尝试对我的服务进行一些负载测试并遇到了这个问题。
有人能告诉我它是否将数据转储到机器上的某个临时位置,然后从那里选择它,因为我没有看到RAM消耗的增加。
我无限调用的方法是AddMessageToList()。
class MainClass
{
List<MessageDetails> messageList = new List<MessageDetails>();
private void AddMessageToList()
{
SendMessage(ApplicationName,Address, Message);
MessageDetails obj= new MessageDetails();
obj.ApplicationName= ApplicationName;
obj.Address= Address;
obj.Message= Message;
lock(messageList)
{
messageList.Add(obj);
}
}
}
class MessageDetails
{
public string Message
{
get;
set;
}
public string ApplicationName
{
get;
set;
}
public string Address
{
get;
set;
}
}
答案 0 :(得分:28)
你的问题的答案是:&#34;在记忆中&#34;。
这可能意味着RAM,它也可能意味着硬盘(虚拟内存)。操作系统内存管理器决定何时将内存分页到虚拟内存,这主要与访问内存的频率有关(尽管我不会假装知道微软的特定算法)。
你也问过为什么你的记忆用法不会上升。首先,MegaByte是一个巨大的内存。除非你的课程很大,否则你需要很多才能出现MB。最终你的内存使用量会增加。
答案 1 :(得分:8)
通常,C#对象是从Heap创建的,它位于内存中。如果你想在磁盘上存储东西,有办法解决它,但标准List<T>
将存在于内存中。
当你创建一个对象时,它将占用内存中的一定数量的字节加上用于引用它的指针的大小。将它添加到列表中只会添加指向您已创建的对象的指针,因此如果您要将同一实例的大量副本添加到列表中,它将不会像您预期的那样快速增长。
如果您真的想测试大数据结构对内存的影响,那么您将不得不提高数字。几千个普通物体不会占用太多内存,但可能会有几百万个。
您可能也对GC.GetTotalMemory()
方法及其朋友感兴趣。
答案 2 :(得分:5)
请注意,Windows(和.NET)上几乎所有内存都是虚拟内存 - 它的“真实,物理”位置是任意的,Windows内存管理处理它。但是,无论它当前是在HDD上使用物理RAM还是页面文件,它都会显示为已提交的私有内存。
因此,您可以实际创建项目并将其添加到List<T>
。有多少个物体?您是一遍又一遍地添加相同的对象,还是每次都创建一个新对象?您使用的是相同的List实例,还是在创建其他实例?您是否保留对创建的对象(和列表实例)的引用,还是将它们丢弃?你真的用对象/列表做任何吗?如果没有,优化器可能已经完全删除了代码(虽然这是非常保守的,所以我不会指望将项添加到列表中 - 这是一个非常复杂的场景,可能有副作用)。
在最低内存理想情况下,你可以使用每个列表项大约四个字节,这并不多 - 你需要262 144个项目来消耗一个MiB内存!
向我们展示您的代码,整个循环及其周围环境。然后我们可以告诉你你实际做了什么。
编辑:这是在WCF服务中?你之前应该这样说过。您在哪里存储 MainClass
课程?如果它在WCF服务类中,它可能不会比单个请求持续更长时间。即使你修复它,并将它存储在一些更持久的东西中,比如静态类,你会遇到收集所有内容,如何重新启动服务等的复杂性。如果你需要安全地保存数据如果时间长于单个请求,则将其存储在进程内存中是不够的。如果您不关心数据偶尔会丢失,您可以使List
实例静态(不会共享,也不会保留)。否则,请使用数据库。
答案 3 :(得分:0)
从您的稀疏描述中推测,您可能没有意识到两种情况:
您看到的15-16 MB的使用情况可能与列表的大小无关:它可能是程序其余部分的内存要求,而您的列表只消耗了可忽略不计的内存量比较。即使你没有明确地创建对象,你的程序仍然需要加载库和东西,这需要记忆。
我不知道C#所以我不知道这是否适用于List
,而是一个标准的容器类实现来动态分配数组来保存对象。 ..如果数组被填充,那么你分配一个两倍大小的新数组并将所有内容复制到新数组并继续(实际比例可能不是$ 2 $)。这可能会导致你的内存使用量长时间保持不变,直到你最终填满数组,然后它突然跳起来,只是长时间保持不变。