首页 > 系统相关 >SocketAsyncEventArgs内存占用太大引发OutOfMemoryExceptions

SocketAsyncEventArgs内存占用太大引发OutOfMemoryExceptions

时间:2023-08-15 23:35:55浏览次数:39  
标签:OutOfMemoryExceptions SocketAsyncEventArgs bytes sendArg 发送 发包 内存 userToken

最近把一个接收socket服务端软件升级为iocp方案,其实就是换成c#的socket的异步方法,主要参考的是微软写的Server类,然后再百度找到基于这个类实现的代码来改造

上线一两天后,软件崩溃了,查日志发现报了很多OutOfMemoryExceptions错误,都是在发送方法上。

因为我发送方法用的SocketAsyncEventArgs是自己new的,不是从SocketAsyncEventArgsPool池里分配的,所以发送后一直没被GC回收掉。

短短5分钟,就占用了1.5G

 

我发送的方法是这样的,微软它的的例子就没这个问题,因为它每个socket接收跟发送都是用的同一个SocketAsyncEventArgs。它是收包后,再发包,然后再收包,这个SocketAsyncEventArgs一直贯穿于里面,但实际场景根本没法跟微软那例子一样,我可能要主动发包给客户端,或者客户端发包给我,我不需要回包给客户,或者客户端发了粘包给我,我需要拆分开发两个包给客户端。所以我接收都是用的同一个SocketAsyncEventArgs,但发送是另外new的。

 public void SendBytes(AsyncUserToken userToken, byte[] bytes)
        {
            if (userToken == null || userToken.Socket == null || !userToken.Socket.Connected)
                return;
            try
            {
                //新建异步发送对象, 发送消息  
                SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs();
                sendArg.UserToken = userToken;
                sendArg.SetBuffer(bytes, 0, bytes.Length);  //将数据放置进去.  
                userToken.Socket.SendAsync(sendArg);
            }
            catch (Exception e)
            {
                UIManager.LogException(e);
            }
        }

我后面也想过也在SocketAsyncEventArgsPool池里面分配,但它这个SetBuffer方法不太懂怎么用,我不知怎么把我的数据传进去,如果SetBuffer(bytes,0,bytes.Length),那它不就引用到我这个字节上,跟bufferManager的缓存数组没引用关系了。也还是会占用内存。

后面查资料时发现这一段话,具体链接 https://www.coder.work/article/1593333   

似乎它这个异步SendAsync本身性能就不是很好,我就用回同步的发包方法Send,改回后就非常稳定了

 

标签:OutOfMemoryExceptions,SocketAsyncEventArgs,bytes,sendArg,发送,发包,内存,userToken
From: https://www.cnblogs.com/caijt/p/17632715.html

相关文章

  • TiKV占用内存超过的解决过程
    TiKV占用内存超过的解决过程背景为了后去TiDB的极限数据.晚上在每台服务器上面增加了多个TiKV的节点.主要方式为:每个NVME的硬盘增加两个TiKV的进程.这样每个服务器两个磁盘,共计4个TiKV的进程因为TiKV其实会使用尽可能多的缓存:storage.block-cache表示RocksDB多......
  • 优化 Redis 集群缓存分配:解决节点间分配不均导致内存溢出问题
    一、Redis集群部署简介在现代应用程序中,缓存被广泛应用以提高性能和减轻后端数据库的压力。本文将探讨面对Redis集群缓存分配不均问题时的解决方法。我们的Redis集群部署包括3主3从,每个节点分配内存4G(服务器总内存32G),内存淘汰策略相同:volatile-lru。二、问题描述在......
  • CUDA之矩阵转置(全局内存、共享内存)
    使用全局内存完整代码链接A合并访问、B非合并访问#ifdefUSE_DPtypedefdoublereal;#elsetypedeffloatreal;#endif__global__voidtranspose1(constreal*A,real*B,constintN){constintnx=blockIdx.x*blockDim.x+threadIdx.x;const......
  • dav 编译报错 v8内存溢出
    dav编译报错v8内存溢出FATALERROR:ReachedheaplimitAllocationfailed-JavaScriptheapoutofmemory  到node_modules中/.bin/roadhog.cmd把最后一句改成endLocal&goto#_undefined_#2>NUL||title%COMSPEC%&"%_prog%"--max_old_space_size=8192......
  • MemoryFile 共享内存原理分析
    Android上层提供了一些内存共享工具类,比如MemoryFile。你使用过吗?知道它的实现原理吗?MemoryFile是Java层对Ashmem的一个封装,下面来一起学习MemoryFile,掌握它的使用姿势和底层原理。MemoryFile使用方法大致如下:「进程A中申请一块共享内存写入数据,并准备好文件描述符:」Mem......
  • C#实现异步阻塞TCP(SocketAsyncEventArgs,SendAsync,ReceiveAsync,AcceptAsync,ConnectAsyn
    //Thisclasscreatesasinglelargebufferwhichcanbedividedup //andassignedtoSocketAsyncEventArgsobjectsforusewitheach //socketI/Ooperation. //Thisenablesbuffferstobeeasilyreusedandguardsagainst //fragmentingheapmemory.......
  • GBase 8s内存不足,扩充表空间
    数据库空间是一个逻辑概念,有多个称为Chunk的物理文件组成,用于存储表或索引的数据。不同的数据库空间可以使用不同的页大小,以便于进行存储性能优化。1.查询当前表空间大小切换到gbasedbt用户执行 onstat-d存储结构介绍(包括物理存储单元、逻辑存储单元、大对象存储)一个......
  • C/C++内存管理
    一、C/C++内存分布看下面这段代码:intglobalVar=1;staticintstaticGlobalVar=1;voidTest1(){ staticintstaticVar=1; intlocalVar=1; intnum1[10]={1,2,3,4}; charchar2[]="abcd"; constchar*pChar3="abcd"; int*ptr1=(int*......
  • C/C++内存管理
    一、C/C++内存分布看下面这段代码:intglobalVar=1;staticintstaticGlobalVar=1;voidTest1(){ staticintstaticVar=1; intlocalVar=1; intnum1[10]={1,2,3,4}; charchar2[]="abcd"; constchar*pChar3="abcd"; int*ptr1=(int*......
  • InnoDB 内存结构
    目录InnoDB架构概念pagepagesizeInnoDB内存架构BufferPool缓冲池LRU算法缓冲池配置ChangeBuffer配置变更缓冲innodb_change_bufferinginnodb_change_buffer_max_sizechangeBuffer的适用场景自适应哈希索引LogBufferInnoDB磁盘架构表索引表空间双写缓冲区RedoLogUndoL......