经测试频繁上传时,内存递增,不会释放
请问下怎么解决呢?
谢谢各位的帮助,谢谢Daniel Cai耐心的指点
2个原因
1:服务器内存足够多,没有触发GC
2:代码有问题,资源没释放
代码我显式释放了,Request.InputStream.Close();
您说的服务器内存足够的情况下,会触发GC,这个临界点是都少,可以算吗?
@待来年山花烂漫之时: 是32位还是64位?其次确认你代码中是不是这些流或者文件句柄对象全部释放了。
如果还是有问题服务器上直接上windbg从!dumpheap -stat后的结果顺着查去。
@Daniel Cai: 64位, 代码里我只用了Request.InputStream, 用完就释放了
@待来年山花烂漫之时: 你先GC.Collect().看一下内存是否释放,如果施放了。那就是GC的问题,不需要担心。在适当的适合GC会自动gc。
如果不是。那就是代码问题了。
不去管它.过一会儿就好了.
我这边过了快30分钟了, 还是没降, 是不是要等到程序池回收的时候才会降呢?
@待来年山花烂漫之时: 不一定.只要你确定没有引用问题.就不用管他.gc自己决定什么时候释放.
有引用存在就永远不会释放.
@吴瑞祥: 嗯,好的,谢谢了。
贴代码来看看啊
代码我取了一部分出来
@待来年山花烂漫之时:
1.64位本来可用空间就要大很多,所以内存吃的比较厉害也正常(而内存持续走高很大原因可能是因为你分配的都是大对象,这种就直接进LOH了,这种被回收的可能性相当小)
2.光你这块代码中间这个byte数组实现就有问题。你应该池化一个byte数组,用完了后还回池中,而不是根据上传大小直接进行分配,然后循环去读取这个stream,只到读完为止这样可以在很大程度上减轻gc压力及内存开销。(但你后面那个service接口参数需要一个数组这个比较操蛋,如果我要上传上g的视频你这里不一条线全跪?)
@Daniel Cai: 额, 视频我们限制50M. 你说的池化能再解释解释吗? 谢谢.
@待来年山花烂漫之时:
用一个对象单独管理,此对象初始化时创建一个足够大小的byte数组,比如50K的长度
然后每次需要的时候从这里借一些,比如1k长度作为stream的缓冲,用完后再还回去。
这样频繁的byte数组分配就没有了。
当然如果你那个service的接口还是那个样的这种就没用了。
@待来年山花烂漫之时: 这种地方如果要这样用池的话这个接口要改,你读了请求后同步flush到某个地址上去
//read 1k per round
while(...read(...))
{
//write to disk or etc.
}
然后直接告诉后面的服务这个地址上就是文件了
这样不仅服务开销小,并发能上去,而且服务上带宽使用也要平缓些。
@Daniel Cai: 好的,受教了,我改下再试试