Herm的Allocator介绍

Allocator可以理解特定对象池。Herm目前有两种Allocator,LiteAllocator和LargeAllocator,前者支持小于120bytes的小对象;后者支持大对象,建议大于120byte以上的对象使用LargeAllocator,小对象当然也支持,但会浪费内存,每个对象将附加8bytes的内存空间。STL也可以直接用Herm的Allocator作为Allocator。


LiteAllocator 在Linux其实就是__gnu_cxx::pool_alloc, Windows上直接弄成std::allocator,因为Herm的定位是开发Linux&FreeBSD的服务器,Windows建议就做客户端。

下面介绍一下LargeAllocator的实现原理。

LargeAllocator内部以Chunk为单位从系统申请内存,默认大小是4K。所有的Chunk形成一个单向链表。

一个Chunk分成X个Block,Block内部有对象的空间。未用的Block形成一个可用的Block单向链表。已用的Block形成一个已用的Block双向链表。由于这个Allocator本身的出发点是支持大对象(>128bytes),所有对链表的生成没做任何优化措施,保证代码简单性。这样会浪费额外的8bytes空间,最大浪费率是:8 / 128 = 6.25%,应该在接受范围内。

下面是Block&Chunk的结构。

struct Block
{
	T obj;
	Block* pre;  
	Block* next;
};

struct Chunk
{
	Chunk* next;
	char buf[1];
};

LargerAllocator维护:

1. Chunk的单向链表(ChunkList)

2.  空闲的Block单向链表(FreeBlockList)

3. 已用的Block单向链表(UsedBlockDeList)


分配一个对象空间

从FreeBlockList取一个Block,把Block内部的T空间返回给调用者。

如果FreeBlockList没有Block了,就要从系统分配一个Chunk,把Chunk加入到ChunkList,同时把Chunk分成X个Block,并把这些Block加入到FreeBlockList中。


释放一个对象空间

其实就是释放一个Block。

从UsedBlockDeList里把对应的Block拿掉,UseBlockDeList是双向链表,拿的动作是O(1)。

将Block放回FreeBlockList的头部。

虑内存访问的效率,链表插入和取出操作都在表头进行。所有的动作都是O(1)。


LargeAllocator的析构

把UsedBlocks归还给FreeBlocks? 归还的过程将调用具体对象的析构函数。
这一步也可以不用归还,就直接在UsedBlocks调用一下具体对象的析构函数,省了O(1)的插入过程。

扫描Chunk链表,把每个Chunk delete掉,内存还给了系统。



1.1 什么是Herm Herm是一套快速开发高性能的网络应用的C++库。比如开发网络游戏、即时通信、流媒体、文件下载、P2P等基于TCP/IP网络应用。 Herm包括三个组件: (1)Utilities 最基础的组件,提供线程、一读一写线程不加锁的ring buffer、二进制消息解析器、支持多态的对象管理器等。 (2)Socket 用面向对象和泛型的方法抽象了TCP/UDP的Socket IOs;抽象了Win32 Select、Linux epoll和FreeBSD kqueue的多路复用API。统一了三者水平模式(Level Triggered)的语义(一套代码在Win32/Linux/FreeBSD运行结果是一样的),Linux上也支持了边缘模式(Edge Triggered)。 (3)Framework 基于Utilities和Socket的简化开发网络应用的框架,抽象出Peer和Session对象。Peer和Session对象以及Framework实现的功能将在第2章介绍Herm目前仅支持Linux/Windows/FreeBSD 32bits平台。调用者可以基于不同的需求使用不用的组件。 1.2 最简单的例子 本节给出两个分别用Framework和Socket组件实现的简单TCP Server的例子。所有的例子可以参考examples frameworks和multiplexors目录。 1.2.1 用Framework实现TCP Server 首先,实现一个Listener, class Listener : public Herm::Listener { virtual void Accept(Herm::Session* session) { // 在这里得到一个于客户端通信的Session // 注册用于处理收到的消息的handler // 用Session::Push将数据写到发送buffer,最终数据传给client } }; 实现一个App, class App : public Herm::App { virtual bool Init() { // 1. 创建Network Herm::Network* net = CreateNetwork(); // 2. 创建一个TCP Server Peer,将Listener注册到Peer,进行监听 Herm::Peer* peer = net->CreateTCPServer(addr, new Listener); } }; 1.2.2 用Socket实现TCP Server 用Socket实现TCP Server更灵活,但实现者要做一些额外的工作,比如tcp stream解析,缓冲队列处理等等。 首先实现一个AcceptHandler,处理Client连接, class AcceptHandler : public Herm::EventHandler { virtual int Receive(int) { m_acceptor->Accept(streamHandler->GetStream()); g_reactor->Register(streamHandler, Herm::READ_MASK); ... } private: Herm::Acceptor* m_acceptor; }; 实现StreamHandler, 处理数据收发, class StreamHandler : public Herm::EventHandler { // Handle onle int param on FreeBSD, pls see the example of FreeBSD_tcp_server virtual int Receive(int) { m_stream->Recieve(buf, .......); ..... } private: Herm::Stream* m_stream; }; 最后,在一个线程里把上面Handler执行起来, while (true) g_reactor->Run(); 1.3 Herm地址 https://sourceforge.net/projects/speed/ 1.4 下一章话题 下章将较详细地介绍Framework组件,主要介绍如何用Framework实现真实可用的网络游戏的接入网关Server(gated)和逻辑Server(zoned) 转自CSDN的herm_lib http://blog.csdn.net/herm_lib
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值