« November 2014 | Main | January 2015 »

December 16, 2014

Dungeon of the Endless

最近一直在玩 Dungeon of the Endless 。按 steam 上的记录,已经超过了 70 小时。今天决定给他在 steam 上写一篇推荐

很羞愧的说,我还没有打过 easy 模式的 Escape pod ,最多到 12 层就挂了。

总的来说,这是近两年我玩过的最好的 Roguelike 游戏,如果放宽一点说,也是最对我粘度最高的一款。很难想像,一个几乎没有成长积累,死了就要从零重新开始的游戏,可以粘住人一盘又一盘的从头开始。而且,玩了 70 个小时没有打过第一关(如果把 escape pod 看作第一个挑战的话)还一直说它的好话。正如游戏那简单的教程最后说的:还有很多可以教你的,不过只要你死的次数主够多,就都知道了。一点点探索游戏的玩法是最大的乐趣。

基本上这是标准的 Roguelike ,有人物成长、有科技升级、有不定期搜集到的装备、有随机迷宫、有突如其来的难题(解决不了就得从零来过)。它的创新点在于掺入了最近几年流行的塔防元素,想想百玩不腻的 Kingdom rush 就知道这是个很惹人喜爱的模式了。

DotE 给人的体验是每道门后的未知刺激,到了 8 层以后更加的明显。随机迷宫的布局真正增加了策略性,在 dust 有限的情况下,你如何布局你的英雄。同时你还得和自己的贪念做斗争:出口已经找到了,我要不要多开一道门?要不要把正在 Operator 的英雄拉过来参战?似乎这拨怪已经拦截住了,省一口 Food 吧?只有在英雄死掉后才追悔莫及。

可是,游戏又总给你留下点希望。有一次我开局不错,到了第 8 层四个英雄都升到了 9 级,工业科技食物攒了一大堆,结果贪心导致死了三个英雄。本来打算放弃的,但抱着试一试的想法,用一个英雄逃离了第 8 层,还在第 9 层还找到了 2 个新同伴。这种起死回生的体验真是非常棒。


说说我是怎么决定买这个游戏的吧。

那天我本来想下单买一个 95% 好评率的 Roguelike 游戏的。但在 steam 上买游戏前都习惯看看差评,打开差评页,赫然发现一个玩家玩了 130 小时还给了不推荐的建议,并洋洋洒洒写了一大篇。我很认真的看完了英文写的评测,觉得写得都挺到位。可是,你也不能太挑了啊,这不好那不好,这样能有你推荐的游戏么?顺着评测,我找到了同一作者给 DotE 写的好评记录。然后就毫不犹豫的下了单。

挑游戏真不容易。几个美刀只够吃顿饭,买下了游戏后投入进去的时间才是宝贵的啊。想想这 70 小时的快乐时光,感谢 DotE 。

December 14, 2014

skynet 社区广州聚会小记

昨天(2014 年 12 月 13 日),忙了一天,终于把说道半年的心事了了。skynet 社区的第一次线下聚会。

一直在 qq 群里说想搞一次线下聚会,让使用 skynet 的同学有机会当面交流一下,忙这忙那的拖到年底。直到又人有重提,择日不如撞日,就选在了本周六。

原来计划搞此 30 人的小聚会就好了,可以就在办公室会议室里。结果没料到公司最近扩张太快,新办公地又暂时没有搞定,会议室都被塞满了。那么转移到楼下餐厅吧,大概可以装下 40 人。

故意没有宣传,想着不会有太多人报名。可到了最后几天,邮件列表上的报名人数超过了 60 人,赶紧去找新场地。最终昨天来了 80 多人。btw. 南京远道来的同学辛苦了。

聚会主要是聚餐和扯淡。中午聚餐时都好沉闷,果然符合服务器开发人员闷骚的个性。几十个人塞在餐厅 2 楼那么一小块地方,都只知道看手机。晚餐熟悉了就好得多了 :D

下午在尚德酒店的多功能厅,四个半小时,搞了 9 个快速演讲。座椅不够,到结束时,依旧有人站着。一反举办这种冗长会议大量中途离场的惯例。

说是演讲,其实就是挑个话题大家好扯淡。当然不只是 skynet 相关的,特别感谢南京自费飞过来的 Ephay Tang 同学给我们分享他们三个人 22 个月制作一款 ios 上独立游戏《僵尸别动队》的苦逼经历。据说即使获得过苹果的推荐,即使在 IGF China 获了奖,还是只卖了一万多份。好吧,我这里赞助一个免费广告:itunes 下载地址在这里 ,3 个人 22 个月加外包部分美术的作品,只卖 25 块哦。注意,不是免费游戏,没有 IAP 的坑给你跳。

非常高兴 skynet 开源两年多以来能收获这么忠实用户。昨天到的朋友居然有一半不是做游戏的。而且大部分都在用 skynet 做项目(剩下的一半有在新项目中使用的计划)。

我真心希望 skynet 不是我的个人项目,也不是我们公司的项目,而是大家的项目。只有用的人越多,他才会更可靠。开源历程中,我们自己的项目也数次防患于未然。在 bug 影响到线上服务器之前就修补了漏洞,这得益于外界的同学提交的 patch 修补了漏洞。

昨天我听到的对 skynet 最好的评价不是它如何高效,如何方便使用,而是它足够简洁。简单到每个用他的人都有信心充分理解它的实现,做到心里有底。想想原来在网易时,即使在大公司内部去推广项目成果都何其困难,大部分项目都宁愿自己做自己的一套东西,也很难接受其他项目组的代码。而 skynet 发展两年多就如此多收获,颇感欣慰。


12 月 16 日

这次活动现场收到 30 人的活动费共 3000 ,网络转账 23 人共 1840 。用于支付活动场地费 1800 ,午餐 + 晚餐 86 人次。

December 08, 2014

乐观锁和悲观锁

最近晓靖给 skynet 提了一个 pr

提之前我们讨论了好久,据说是因为查另外一个问题时改写了 skynet 的消息调度部分发现在某些情况下可以提高 CPU 的使用率。

之前 skynet 的消息调度采用的是基于 cas 的无锁结构。但本质上,并发队列这种数据结构,无论是采用 spin-lock 还是 cas 无锁结构,为了保证时序,进队列或出队列的部分都必须是依次进行的,也就是说,多核心无助于提高队列的性能。

使用无锁结构,无非是对发生冲突保有乐观态度,觉得大多数情况下冲突不会发生,一旦发生就采取重来一次的策略。

而使用 spin lock ,则是对冲突采取悲观策略,认为冲突经常发生,所以在操作共享字段时,锁住资源独享操作。

最终,都必须等前一件事情做完,才能接着做下一件事。

无锁结构的程序逻辑往往显得复杂,那么它的好处是什么呢?

无锁结构在乐观情况下,可以让处理过程尽量并行,只在可能发生冲突的那一刻才用系统的原子指令锁住一个字长的内存写入,然后立即放开。加锁和解锁是原子的,这样就可以回避死锁的问题。同时也不会因为 spin lock 锁住的指令过多(如果线程数多于核心数,就有可能在锁住的过程中发生线程挂起),而导致其它线程等待时间过长。

在 skynet 的核心消息队列调度模块中,无锁结构能获得的好处其实非常有限。为了简化代码,我们甚至不需要单独去锁队列的两端。因为在 skynet 的消息队列分两级。在运行过程中,如果此级队列有消息时,它根本不会进入全局主队列(用锁保证次序的那个队列)。


由于不再使用无锁队列,数据结构也可以大大简化。使用一个简单的单向链表就可以管理这个队列。之前为了解决队列长度问题,已经把次级队列设计成一个侵入式链表,这次要做的只是把那个数组部分去掉就可以了。


修改过后,一个明显的好处是突发的大量服务启动(往往是瞬间大量连接涌入造成的 agent 启动需求)变快了。这解答了之前的一个疑问


12 月 12 日补充:

这篇不在于讨论用乐观锁还是悲观锁的性能好坏. 上文最后提到的问题的解释, 并不是因为提高了锁的性能, 而是因为:

之前认为在 skynet 的多个 worker 竞争全局队列时, 抢到操作权是乐观的. 因为处理消息本身的时间远远长过操作全局队列的时间. 当多个 worker 竞争时, 我们认为几乎是不会冲突的.

所以在 worker 竞争全局锁时做了这样的处理: 如果失败, 就认为队列为空, 而不是重新尝试. 这样做可行是因为 worker 本身是对等的, 每个 worker 的职责是完全相同的。

一旦发生竞争,说明 worker 没有什么复杂的事情做(当消息处理时间足够短时,竞争的概率会上升),所以让竞争失败的 worker 暂时放弃更有助于节约系统的资源。即:如果任务不多,退化成单核处理更好。

这样实现倒不是为了提高性能,而是代码更简单(不需要再重试)。

这次发现在某些特定情况下,这个策略是错误的。至于改成 spinlock ,是因为代码量要小的多。而在队列实现上,无论采取怎样的策略,对系统的性能影响及其有限,那么选择一个代码更简单的实现更好。