Phoenix@上海

Software Evolution

用户操作
[即时聊天] [发私信] [加为好友]
phoenixshID:phoenixsh
22567次访问,排名5702(1),好友0人,关注者2人。
phoenixsh的文章
原创 22 篇
翻译 1 篇
转载 1 篇
评论 43 篇
phoenixsh的公告
所有文章除注明转载或者翻译之外,均为原创。转载请注明出处,谢谢!
最近评论
linkerlin:您认为的长字操作是原子的认识是不准确的.
要考虑跨核心L3Cache的影响.
wannabe:还好没人遇到thrashing
coolspeed:深感于LZ观点,可能因为我也是学微电子的,所以特别认同。

做软件的人早已习惯了把硬件(芯片)当成黑铁盒子,他们推崇通晓软件的细节。所以对于库(这也是黑铁盒子)的使用的学习是相当不满的。主要,矛盾在于,当体系变得复杂,非本质复杂性的巨增,封装成透明盒子和黑铁盒子的区别变得不大,使用起来,可以认识的只是表面(黑铁盒子的外壳)。无法指望所有人都通晓架构。

passos:我觉得学生学到的第一种语言可能对他的思维方式产生极大的影响。俗话说,由俭入奢易,由奢入俭难。习惯了Array.sort了方式,可能从潜意识中就不太会关注细节,导致真正到了需要关注细节的时候,又无法或没有能力去掌控细节。
phoenixsh:孟大侠光临寒舍,不敢不认真啊。

不过我看孟大侠的意思,也只是说明B.S.教C++比别人教Java更成功而已。

也许我们第一门课应该先讲量子力学,然后讲晶体管的开关特性,最后给大家电烙铁去整一个与非门出来?或者,我们应该先讲图灵机原理?
文章分类
收藏
    相册
    数学公式
    技术新闻
    ACM Tech News
    网络杂志
    ACM Queue
    友情链接
    absurd
    eXcel
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 高效网游服务器实现探讨(一)收藏

    新一篇: 高效网游服务器实现探讨(二) | 旧一篇: 晕,人民银行也干这种事情!

    高效网游服务器实现探讨(一)

    转载请注明出处:http://blog.csdn.net/phoenixsh

    随着多核处理器的普及,如何充分利用多核并行工作就成为高性能程序设计的一个重点。本系列文章将围绕高性能网游服务器的实现,探讨这方面的技术。

    网游服务器的特点是:

    具有大量客户端连接(数百至数千个),每个客户端都以一定的速率不断发送和接收数据;
    服务器端的数据流量通常在几个至几十个Mbps之间;
    数据需要实时处理;
    数据包具有时序关系,往往需要按照严格的先后顺序予以处理。

    网游服务器实际上代表了一类典型的新兴流数据处理服务器。这里只是为了讨论方便而限定于网游服务器,但是所讨论的原理和技术应该是普适的。

    同步多线程技术肯定是无法满足要求的。由于每个客户端都在持续和服务器交换数据,系统将无法有效管理太多的线程;即使使用线程池技术,所能服务的客户连接也是很有限的。至于数据处理的实时性和数据的时序都无法顾及。

    异步技术有好几种方式,这里只讨论IOCP和轮询模式。IOCP是微软推动的技术。对非常大量的连接(数千至数万)很有效。但是由于使用了多线程,这些线程需要把所需读写的数据通过共享的FIFO与主线程解耦(否则无法保持时序)。这就造成频繁的线程切换,无法满足大数据量的实时处理要求。另外,由于网卡只有一块(就一个网络地址而言),多线程并不能增加读写的速率。在另外一些时序要求不那么严格的场合,这些线程可以各自独立完成所有的处理任务,只需要在线程内部保持数据的时序。这就是向同步多线程技术退化了。

    轮询是常用的模式。程序员把需要处理的Socket连接注册到一个数据结构中,然后提交给系统检查它们的读写状态。系统返回可供操作的Socket连接列表供程序员逐个处理。如果有数据可读就读入并处理,如果可写则把相应的数据写出去。为了提高效率和程序结构的清晰起见,Socket服务器通常单独使用一个线程,并且通过FIFO数据结构和主线程解耦。

    在单核处理器上,上面这种轮询的模式是没有问题的。但是在多核平台上,用于解耦的FIFO将会变成并发瓶颈。这是因为传统的实现技术必须对FIFO加锁。虽然网络线程和主线程分别跑在不同的核上,理论上可以物理同时地运行(如果分别操作不同的数据项),但是同步锁却强行迫使其中的一个线程必须等待另外一个线程退出临界段,即使另外一个核空闲着。

    这时候就需要一种支持并发的数据结构,下面称之为ConcurrentFIFO。

    public interface ConcurrentFIFO {
        public Object remove();
        public void put(Object o);
    }

    put方法把一个数据对象推进FIFO,而remove方法从FIFO删除并返回一个数据对象。通过精心设计,ConcurrentFIFO的实现是线程安全的,两个线程可以安全而同时地访问FIFO。这样在多核平台上就能达到极高的性能。

    通用的ConcurrentFIFO是非常难于实现的。基本的技术是使用原子的CAS操作来实现。CAS即CompareAndSet。现代处理器基本上都能支持这一类指令。但是这种数据结构的实现的一个很大的障碍就是垃圾回收。在多线程并发运行的情况下,被原子替换下来的数据无法得知其是否是其它线程所需要的,也就无法决定是否回收这块内存。除非有垃圾回收器,否则ConcurrentFIFO是很难实现的。(鼓吹手工管理内存效率最高的朋友们请瞪大眼睛看清楚)

    其实,即使是对于有垃圾回收和内建线程支持的Java语言,要想构造一个支持并发的数据结构,也是极端困难的。java.util.concurrent包是经过并发领域的专家(Doug Lea,同时也是早期lig++的主要作者,以及DLmalloc的作者。我后面讨论内存管理的时候还要提到他)精心编写,并且由java社区的许多专家仔细评审测试之后才发布的。

    我在这里当然不打算自己实现一个通用的ConcurrentFIFO。Java语言的使用者是幸福的,因为这些东西标准库里面已经提供了。(C++版本的恐怕要等到C++0x出来了。听说还有很多人反对C++增加垃圾回收器,那样可够悬的。)但是考虑到网游服务器主要还是使用C/C++编写,我将尝试提供一个C或者C++版本的实现,只能供单线程读单线程写(Single Reader Single Writer),使用细粒度锁实现(而不是CAS技术)。虽然简陋了点,但是能够满足需要。不过我最近很忙,而写这种东西又非常费时间,所以我不能保证什么时候才有下文。今天太晚了,就先写到这里。

    发表于 @ 2007年03月07日 00:55:00|评论(loading...)|编辑

    新一篇: 高效网游服务器实现探讨(二) | 旧一篇: 晕,人民银行也干这种事情!

    评论

    #pass86 发表于2007-08-08 13:33:15  IP: 60.212.249.*
    期待C++0x,垃圾回收某些时候是必要的。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © phoenixsh