摘要: 以前写过一编博客介绍我们游戏的AI服务器。基本的结构就是利用windows的fiber,在每个fiber中运行一个lua虚拟机,具体的内容可以产参看http://blog.csdn.net/sniperhuangwei/article/details/5425471但这个方案有一个缺点,就是随着项目的推移,AI脚本变得越来越复杂,每个虚拟机占用的内存就变得越来越大。当一个进程上运行的AI对象数量很大时这个进程就吃掉了非常大的内存。经过一番考量,我决定不使用windows的fiber来支持用户态线程调度框架,而是改用lua的coroutine.这样整个进程只需要维护一个lua虚拟机就够了,即使A 阅读全文
posted @ 2012-04-02 09:40 sniperHW 阅读(3385) 评论(0) 推荐(2) 编辑
摘要: unix一个传统的服务器模型就是一连接一进程模型。进程对地址空间的保护作用是显而易见的,为某个连接服务的进程出现错误导致崩溃,其它的进程还能正常的运行。但是,当连接数大时,创建过多的进程显然会影响效率。那么启动一系列的进程,每个进程都利用epoll为多个连接服务,不是就可以避免创建过多的进程,同时也利用到了进程地址空间保护的优势了吗?但是还有一个问题,我们不能为每一个进程都创建一个监听套接口。unix系统还有一个特性,就是可以将一个文件描述符传递给其它进程,方法有很多,unix域套接字是其中一种办法。利用unix域套接字传递文件描述符,就可以用一个进程监听套接口,将到来的连接传递给其它进程,由 阅读全文
posted @ 2012-04-02 09:35 sniperHW 阅读(4326) 评论(1) 推荐(0) 编辑
摘要: 前面一篇文章实现了一个抢先式的用户级多线程框架,现在用那个框架编写一个echo服务,因为只是个实验,所以代码写得比较杂乱,还有很多可能出错的情况也没有处理,这些在今后的进一步研究中都会慢慢修改,下面是代码:uthread.h/** brief: 用ucontext实现的用户级线程框架* author: kenny huang* date: 2009/10/13* email: huangweilook@21cn.com*/#ifndef _UTHREAD_H#define _UTHREAD_H#include <ucontext.h>#include <stdio.h> 阅读全文
posted @ 2012-04-02 09:32 sniperHW 阅读(1256) 评论(0) 推荐(0) 编辑
摘要: 以前曾经写过一篇blog,使用linux ucontext实现的用户级多线程框架.那个框架实现的是协作式多线程序,也就是只有当正在执行的coroutine主动放弃处理器时,其它coroutine才有机会得以执行.今天用ucontext实现了一个抢先式的用户级多线程框架,其主要思想是,用一个物理线程作为中断发生器,以固定的时间间隔发送SIGUSR1信号.另一个物理线程运行Scheduler和用户级线程。每当这个物理线程收到信号的时候,就会将执行权切换到Scheduler,由Scheduler挑选一个个用户线程执行.thread.h// C/C++ header file// Author: .. 阅读全文
posted @ 2012-04-02 09:31 sniperHW 阅读(2653) 评论(4) 推荐(1) 编辑
摘要: 昨天看CN-Erlounge-IV讲搞的其中一篇<erlang进程模型在C++中的实践>,对用coroutine实现用户态的线程非常感兴趣,于是查下资料写了个简单的实验框架,其中schedule算法的实现很简单,只是遍历所有可以执行的coroutine.代码如下:uthread.h/** brief: 用ucontext实现的用户级线程框架* author: kenny huang* date: 2009/10/13* email: huangweilook@21cn.com*/#ifndef _UTHREAD_H#define _UTHREAD_H#include <uco 阅读全文
posted @ 2012-04-02 09:28 sniperHW 阅读(3540) 评论(0) 推荐(0) 编辑
摘要: 曾经参与过的一款网络游戏,其服务器使用了异常复杂的多线程序解决方案。导致应用层程序员编写的代码很容易就出现死锁。最终,公司的一个老员工,只能开发了一个死锁检测框架,在debug模式下运行时,只要发生死锁就会打印出调用堆栈。虽然说这个框架基本可以在上线前把所有的死锁都检测了出来,但是,规根到底这是设计不合理造成的,多线程利用好了会提升应用的效率,用不好的话,除了影响效率外,对上层开发简直是灾难。下面说说那个检测方法,其实方法挺简单的。有两个容器,一个用于保存线程正在请求的锁,一个用于保存线程已经持有的锁。每次加锁之前都会做如下检测:1)检测当前正在请求的锁是否已经被其它线程持有,如果有,则把那些 阅读全文
posted @ 2012-04-02 09:26 sniperHW 阅读(7106) 评论(10) 推荐(0) 编辑
摘要: 随着处理器往多核的发展,多线程被越来越多的应用到软件的开发中。但是如果没有正确的使用多线程,反而可能会导致软件性能的下降。多线程程序中一个影响程序性能的因素就是同步。对于windows系统来说,最快的同步方案就是critical_section,critical_section基本上可以被认为是一个用户态的同步机制(特别是设定了spincount,只有在自旋超过了spincount次之后任然不能获得锁,才会切入核心态并把当前线程阻塞).但即使是这样,如果在临界区中的代码如果处理时间比较长,任然会导致处理器浪费在自旋上。如果我们可以让线程在无法获得锁的时候就切换线程(当然是在用户态,切换核心态线 阅读全文
posted @ 2012-04-02 09:24 sniperHW 阅读(2110) 评论(7) 推荐(0) 编辑
摘要: 接上篇,本文介绍发送封包的设计.WPacket的构成与RPacket类似,实际数据都存放在buffer组成的链表中.发送时,如果一个WPacket的数据跨越了两个buffer,可通过WSASend提交多个缓冲,一次性将数据发出去.WPacket还提供了一个传入RPacket的构造函数,以方便网关类程序收到一个包就马上将其转发的需求.一般情况下,从一个RPacket构造的WPacket都不需要向其写入新的数据,而是直接转发.所以.构造的这个WPacket和传入的RPacket是共享buffer的.这样大大减少了内存拷贝的次数.当第一次向这个WPacket写入数据时,将会触发拷贝过程,将RPack 阅读全文
posted @ 2012-04-02 09:17 sniperHW 阅读(2284) 评论(6) 推荐(2) 编辑
摘要: 网络程序,为了提高程序的性能,应尽量减少内存的拷贝次数。以windows IOCP为例,complete线程在接收到数据后,应该马上将接收到的数据拷贝到解包缓存,然后立即发起一次新的WSARecv操作。然后再对解包缓存执行操作,解析出逻辑包。通常的方法是将数据拷贝到一个环形缓冲中,以减少数据的拷贝次数。但在解出一个数据包之后,免不了还要将一个完整的数据包拷贝到另一个包缓存中,再将这个包提交给应用层处理.本文介绍一种,拼包方式,以避免从解包缓存copy数据到逻辑包中.首先介绍逻辑包的组织结构://RPacket数据可跨越多个bufferclass RPacket{ friend class... 阅读全文
posted @ 2012-04-02 09:16 sniperHW 阅读(1823) 评论(5) 推荐(1) 编辑
摘要: 本篇介绍另外一个在C++ stl中常用的容器map.我打算将map的实现容器和map接口分开,创建map的时候可以传递一个实现了interface_map_container接口的对象指针进来,如果这个参数传0,则默认使用红黑树做实际的容器.这样做的好处是用户可以根据性能需求传递自己定制的容器类.例如在游戏程序中常见的数据表.一般通过一个索引查询,并且在程序启动时候将数据全部加载好,在以后的运行中,只会对数据进行查询,不会做任何修改的动作.在这种情况下,使用一个数组存放key,val对,再加载完成后对数组排序,后面查询的时候使用2分法,显然比用红黑树或其它的二叉平衡树效率更高.好了,下面介绍m 阅读全文
posted @ 2012-04-02 09:12 sniperHW 阅读(1730) 评论(13) 推荐(1) 编辑
摘要: 这是我的工具库中最后一个内存分配相关工具,其主要用途是,在某一函数或一个作用域中需要使用动态内存,出了这个作用域之后,马上就释放这些分配的内存.其主要工作模式是,函数开始时分配一大块内存,由分配器管理,函数中需要使用的动态内存全都由分配器从这块大的内存中分配出来,分配出来的内存无需free,函数返回之前销毁分配器,由分配将开始分配的大块内存释放.local_pool.h#ifndef _LOCAL_POOL_H#define _LOCAL_POOL_Htypedef local_pool *local_pool_t;/** pool:外部传进来的大内存块首地址,当这个参数不为0时,* ... 阅读全文
posted @ 2012-04-02 09:09 sniperHW 阅读(839) 评论(0) 推荐(0) 编辑
摘要: 本篇将介绍一个通用内存分配器的实现.上一篇的开头已经介绍过,这个实现是组合first fit pool和fix_obj_pool以处理不同大小的分配请求.首先看由fix_obj_pool返回的内存的头结构:struct head_fix{unsigned short idx;/*0-255,表示在fix_objs的下标*/unsigned short chunk_idx;};这个头不会返回给上层应用,是给释放内存使用的.因为内存的请求是对齐到4字节的,小于1024字节的请求,被分成256个分配大小,分别是4,8,12,....1024.每个大小的请求由一个fix_obj_pool处理.idx的 阅读全文
posted @ 2012-04-02 09:07 sniperHW 阅读(1018) 评论(0) 推荐(0) 编辑
摘要: 本篇介绍通用内存分配工具的另一个组件,first fit momery pool,也就是首次适应内存分配器。相对于best fit 算法,通常来说first fit具有更好的平均性能,具体分析可参考kunth计算机程序设计第一卷2.5的讨论.我的通用内存分配器准备组合使用fix obj pool和first fit pool.fix obj pool用于处理1-1024字节的小内存请求.这里分配的内存是对齐到4字节的.而对于1-1024字节以外的大内存块请求,将交给first fit pool处理.为了加快free时的处理效率,将对fix obj pool做一个小处理,具体将在下篇通用内存分配 阅读全文
posted @ 2012-04-02 09:06 sniperHW 阅读(1093) 评论(2) 推荐(0) 编辑
摘要: vector.h#ifndef _VECTOR_H#define _VECTOR_Hstruct vector;struct vector *vector_create(unsigned int val_size,unsigned int reserve_size);struct vector *vector_copy_create(struct vector*);void vector_copy(struct vector*,struct vector*);void vector_reserve(struct vector*,unsigned int);void vector_destroy 阅读全文
posted @ 2012-04-02 09:03 sniperHW 阅读(1279) 评论(0) 推荐(0) 编辑
摘要: 对大小固定的对象提供的对象池工具,当对内存分配的请求大小不固定时,使用其它的通用内存池.fix_obj_pool.h#ifndef _FIX_OBJ_POOL_H#define _FIX_OBJ_POOL_Hstruct fix_obj_pool;/** obj_size:对象大小* default_size:默认对象池大小* align4:返回的对象地址是否需要对齐到4字节*/extern struct fix_obj_pool *create_pool(unsigned int obj_size,int default_size,int align4);extern void destro 阅读全文
posted @ 2012-04-02 09:02 sniperHW 阅读(1306) 评论(1) 推荐(2) 编辑
摘要: 使用setjmp,longjmp实现的C与言异常处理框架。提供 抛出异常,捕获异常等功能。exception.h#ifndef _EXCEPTION_H#define _EXCEPTION_H#define except_alloc_failed 1 //内存分配失败#define except_list_empty 2 //list_pop操作,当list为空触发//............#endifexcept.h#ifndef _EXCEPT_H#define _EXCEPT_H#include <setjmp.h>#include <stdio.h>#incl 阅读全文
posted @ 2012-04-02 09:00 sniperHW 阅读(717) 评论(0) 推荐(2) 编辑
摘要: 近来考虑将项目基础框架的开发语言从C++换成C,免不了要编写一大堆的基础工具。本篇为第一篇,list,提供的接口和操作方式与std::list相似.后续将会陆续贴出map,vector,memory pool,hash_table等工具。list.h#ifndef _LIST_H#define _LIST_Hstruct list;struct node;struct fix_obj_pool;struct list_iter{ struct node **next; struct node *n;};struct fix_obj_pool *list_create_obj_poo... 阅读全文
posted @ 2012-04-02 08:55 sniperHW 阅读(1924) 评论(3) 推荐(0) 编辑