Closed smallnewer closed 6 years ago
内存方面可以采用Buffer存储数据+定义数据类型+数据操作抽象接口+接口预编译为对Buffer的操作
的组合拳。
各有其目的:
其中最麻烦的,就是Buffer如何管理数据了。目前我还没具体方案,但感觉应该会模拟现有语言如C++的一些数据类型的内存布局了,比如Map、Vector、定长数组、链表这些东西。字符串为了提高操作性能,可能也会借鉴V8的一些优化技巧吧。
之前测过,对hidden class的属性读操作和对Buffer的下标读操作,Buffer是落后的,可能是有越界判断。但是也很接近了。比无法JIT优化的代码或者使用hash的对象要快多了。
为了用JS,我也是拼了。不过这也是乐趣所在。
关了。
我用JS写游戏服务器也有蛮久了,用它支撑起一款轻量级的MMORPG(手游这种基本都算中轻度以下了)已经没问题。 虽说带起来是没问题,但还是很不顺手,究其原因大概就是一句话:写的爽但性能低,性能高写的就不爽。这就让我一直想把JS带到类似Golang的负载体量上来。 JS写游戏服务器真的有太多的槽点:
今天就在想,这样的设计下,JS承载了太多责任(许多是JS不适合的),就如同NodeJS的思路,连协议解析这类的工作都交给JS,这样留给业务的时间就更少了(虽说现在优化的很牛,和Golang可以一战,但那只是压测而已,实际业务中,JS对性能的影响很不稳定,这也并不是出套规范能解决的)
那么我们按照Skynet的Actor模型来设计会怎样呢? 首先我希望的是:
下意识想到的实现方案:
比如我们可以做成一个玩家就是一个actor。当来消息时,快速的传到原型链上的函数(可以被高度JIT优化),进行简单的逻辑运算,返回数据。虽然会限制JS的自由度,但为了性能,完全可以接受。 和Skynet有很大不同的是,一个actor是一个独立的作用域,而JS这边的actor只是一个类。不过这个也有解决办法,我们可以利用闭包来给每个actor一定的作用域。但这有一些副作用,比如容易影响到对函数的JIT优化,比如对内存的利用率等等。不过应该也在可以接受的范围内。 主要的问题是出现在和其他actor交互时,比如完成一场战斗,我们需要增加对战记录。那么有actor A会发起对actor B的请求,要求B自己也增加一份记录。 正如上面说的,这个方案传递消息也不例外,必然要涉及到序列化,而不能像其他语言一样,直接一个memcpy过去,甚至连copy都没有。性能会大打折扣。 不过反过来我们也可以这么看,这个消息的开销是否可接受的,毕竟在大部分游戏里,和其他人的数据交互不是高频操作。 地图actor可以分布在任何线程里,由玩家actor接受客户端消息,直接转发到地图actor里(最多多一次消息copy,若在同线程内则无需copy-约等于0开销),甚至可以由客户端直接给某个actor发消息。 为了提高性能,我们可以会把同分区的玩家安排在同一进程内,减少跨进程的通信。该分区的数据也可以做成一个actor(这里就有问题,和分区数据交互可能是一个高频操作,需要频繁读取,待解决)。 Actor模型的一个大问题就是吃内存。JS的内存占用会显得比较严重。 到此为止,此方案应该可以解决JS如果更有效的利用多线程的问题,但内存问题仍然没解决。 留作疑问,日后思考。