如题!

解决方案 »

  1.   

    如果简单的内存管理,可以考虑每个客户端开个环形缓冲区,复杂一点的开内存池(无上限,可增长的),每个客户端使用内存块缓存机制(从内存池获得,使用完毕后放入内存池),再加上通讯内核和其他部分的异步机制,可以收到较好效率和较低CPU占用率。
      

  2.   

    楼上的办法也是一次分配多个内存,释放只是你标识释放,不返回给操作系统,这样确实可以获得比较好的效率和较低的CPU占用率。
      

  3.   

    如果简单的内存管理,可以考虑每个客户端开个环形缓冲区,复杂一点的开内存池(无上限,可增长的),每个客户端使用内存块缓存机制(从内存池获得,使用完毕后放入内存池),再加上通讯内核和其他部分的异步机制,可以收到较好效率和较低CPU占用率。
    =======================================
    比如向系统申请了100M的内存作为内存池, 怎么一块一块分给客户端使用? 每次从内存池取的大小是固定大小还是按接收到客户端数据的大小来取出; 还有如果是按固定大小取出, 考虑系统的页大小不, 每页为4K; 如果按接收客户端数据大小来取内存池的空间, 我们怎么去维护这个内存池? 
      

  4.   

    向系统申请的时候按“页”的整数倍申请就可以,至于你如何使用已经不会影响到碎片,最多只会由于使用不合理产生逻辑碎片,导致内存使用上造成浪费,虽然这跟在系统级造成碎片没有太多差别,但是只影响到你的程序,或者说别的程序不会对你的程序造成影响。可以为应用程序申请多个内存池,最好每一个内存池使用不同的堆(heap),在需要清理的时候,可以让程序将整个内存池关闭申请,从而在一定时间内就能够全部被释放为闲置的,于是就又形成了一个完整的内存池(块),如此就可以循环使用。只对于需要频繁申请和释放的数据使用内存池内存,对于那些生命周期较长甚至是常驻的数据就不需要使用内存池内存。对于网络应用,一般建议使用相对固定的内存片,比如socket的缓冲区一边为8K,那么你的内存块就可以使用8K为最小单位,如果一次性接收的数据只有几十或者几百个字节,可以循环使用该内存块,当碰到当前内存块不足以接收整个应用报文时,可以采用链式内存,也可以重新申请足够的内存块,然后将已有数据进行复制,通常情况下,建议使用数据长度指示使用,替代关键作为报文边界,而指示数据长度的数据(数值)一般被排到最前面,从而可以在接收到少量数据时就能够进行内存的重新分配,如此导致的复制量是相对较小的。
      

  5.   

    这个地址有一个例子,楼主参考一下:http://blog.csdn.net/Bear_hx/archive/2008/11/28/3403953.aspx
      

  6.   

    function TMemoryManager.Allocate: PIOCPStruct;
    var
      i: Integer;
    begin
      FLock.Enter;
      try
        Result := nil;
        for i := 0 to FList.Count - 1 do
        begin
          Result := FList[i];
          if not Result.Assigned then
            Break;
        end;
        if (not Assigned(Result)) or (Result.Assigned) then
        begin
          New(Result);
          FList.Add(Result);
        end;
        FillChar(Result^, SizeOf(TIOCPStruct), 0);
        Result.Assigned := True;
        Result.Active := False;
      finally
        FLock.Leave;
      end;
    end;这段代码的效率太低了。如果内存池中有几万个元素,在高并发的时候,需要命中的位置都在几千甚至几万的下标当中,那么这个选择Result.Assigned = false的for循环操作有多少是在浪费时间?基本上本意想提升效率,却在这里形成了瓶颈,这不就适得其反?
      

  7.   

    一种浮跃式(泡沫式)的池管理,仅供参考
        with FMemoryList.LockList do
          try
            if Not lpBuffer^.Using then Exit;//非在用内存        lpBuffer^.Using :=  false;//闲置        //FLastUsing 指向最后一块被分配内存下标的指针,-1表示没有使用,在这里几乎是不可能出现的
            if FLastUsing >= 0 then 
            begin
              //将最后一块被分配的内存与当前须释放的内存交换位置(下标)
               //虽然每次释放都多了一个交换操作,由于在分配的时候,以及被交换的时候,都有更新自己所属的下标WhereXY
               //比起循环查询闲置内存,效率就要提升很多
              lpTempBuffer  :=  Items[FLastUsing];
              if lpTempBuffer <> lpBuffer then
                begin
                  //交换所属下标记录
                  lpTempBuffer^.WhereXY         :=  lpBuffer^.WhereXY;
                  lpBuffer^.WhereXY             :=  FLastUsing;
                  //交换位置
                  Items[FLastUsing]             :=  lpBuffer;
                  Items[lpTempBuffer^.WhereXY]  :=  lpTempBuffer;
                end;
              Dec(FLastUsing);        end;
          finally
            FMemoryList.UnlockList;
            self.Free;//每申请一个内存都对内存管理器增加一个引用计数,所以这里加以释放
          end;
      

  8.   

    分配内存片断      with FMemoryList.LockList do
            try
              if (FLastMember <> FFirstMember) and (FLastUsing <> FLastMember) then
                begin
                  //有闲置内存,取最前面一块闲置内存标示为占用
                  Inc(FLastUsing);
                  lpBuffer  :=  Items[FLastUsing];
                  Result    :=  lpBuffer;
                end;
              if Result = nil then
                begin
                  //没有闲置内存,则申请新内存
                  lpBuffer  :=  CreateNewBuffer(LocalBytes);
                  if lpBuffer = nil then  Exit;
                  //新内存增加到列表当中,并更新其“所属下标”
                  lpBuffer^.WhereXY := Add(Pointer(lpBuffer));
                  Result            :=  lpBuffer;
                  Inc(FLastMember);
                  FLastUsing        :=  FLastMember;            end;          Result^.Using           :=  true;
              Attach;  //内存申请成功,则为内存管理器自身增加一个引用计数
            finally
              FMemoryList.UnlockList;
            end;
      

  9.   

    内存池的管理无非就是上面的代码,一个是申请的先从池子里面找闲置资源,没有则创建新的,然后放到池子中进行管理.释放的时候放到池子当中置为闲置状态.剩下的就是什么New/Alloc等之类的,再就是也可以在类似CreateNewBuffer的时候判断是否超出池内存限制,对于超出限制时返回一个NIL.
      

  10.   

    lz,只是进行内存池管理的内容进行讨论,可俺是冲IOCP来的!
    不过看了几位的大佬的评论,还是挺有收获和共鸣的!
    呵呵呵呵