一个格式化文本信息版面的小玩意
bgfx 提供了一组调试文本输出的 api ,可以把一些文本信息显示在屏幕上。这些 API 非常简陋,只是提供了一个文本模式缓冲区。离控制台还很远。
具体见 文档中 的 dbgText* 系列函数。
随着我们的游戏引擎中越来越多的信息需要展示,直接使用这些 api 就越发简陋了。最近萌发的想法是干脆使用 imgui 来绘制调试信息界面。但我又觉得保留 bgfx 自带的这个文本模式也有一些好处。
bgfx 提供了一组调试文本输出的 api ,可以把一些文本信息显示在屏幕上。这些 API 非常简陋,只是提供了一个文本模式缓冲区。离控制台还很远。
具体见 文档中 的 dbgText* 系列函数。
随着我们的游戏引擎中越来越多的信息需要展示,直接使用这些 api 就越发简陋了。最近萌发的想法是干脆使用 imgui 来绘制调试信息界面。但我又觉得保留 bgfx 自带的这个文本模式也有一些好处。
云豆想要一块电话手表。我了解到现在的小孩大多用小天才儿童手表,但考虑到云豆其实没有什么社交需求,我自己也有一块 apple watch ,所以想试试给他买一块。最初的想法是,儿童手表过两年估计娃就不愿意带了,而 apple watch (系列)可以用到成年。而似乎 apple 似乎也愿意做儿童市场,现在 apple watch 有家人使用的模式,不妨试试。
周六,网上订购的 apple watch se 到了。我给他创建了一个苹果的儿童账号,很顺利的就设置好了手表。但简单适用了之后就被劝退。apple watch 的家人模式功能上大打折扣,手表其实还是挂在我账号下的,而表上多绑了一个儿童账号。这导致除了苹果官方默认 app 之外,几乎所有的 app 都不能安装。包括微信支付宝这些。除了打电话,能用的通讯就只剩下 iMessage ,对小孩几乎没什么用。我想在手表上装个交通卡也未能成功:因为年龄不够(苹果要求 14 周岁),不能在钱包里添加卡片。苹果官网查了一下,儿童账号的支付功能只在美国才能开。
最近 AI 很火。我从读书的时候就对 AI 有兴趣,90 年代的时候读过一本关于神经网络的书。但当时没有能力完全理解。2000 年初刚毕业那会儿想搞明白点,又研究过一段时间。了解了很多相关知识,感觉自己弄明白了,但却没有真正动手实践过。
现在,所有人都看得到,AI 已经变成了一个可以真正帮助我们提高生产力的工具了。我觉得有必要好好学习一下。我并不期望几篇文章就可以搞清楚,那样只会让自己好像懂了,和人聊天估计够用,想理解它还是得自己动手。真正写几段代码,才有触碰的感觉,明白别人到底在解决什么问题。
一开始,我是从维基百科的 Machine learning 开始读的。顺着看了一整天,了解了近年发展的脉络。好多词条,乱七八糟的笔记记了一大堆,感觉快消化不了了。疑问也积累了很多,觉得看下去效率会越来越低。不如换一条路。
然后我开始读 Neural Networks and Deep Learning 这本书。读了两章后,我想,手写数字识别看起来是一个非常好的实践手段,不如自己写一遍最快。有这么一个基础,后面可以继续修修补补,沿着前人的轨迹走一下,可以更好的理解为什么。
周末在家里折腾 BT 下载,发现 UPnP 无法工作,便去光猫那里看看是什么情况。
我发现现在电信宽带默认已经是由光猫来拨号,家中的路由器是作为一个二级路由在使用,如果想让 UPnP 或 DMZ 工作起来,需要在光猫里设置。
查看光猫设备上印的默认管理员密码登录上去,没有找到太多设置选项。在网上搜了一下,需要一个超级管理员身份才能看到全部设置菜单。一般的说法是打电话问一下装宽带的师傅,但天色已晚,不想麻烦人。转念一想,有这么多家宽带设备要管理,电信应该用的是统一密码,或是有一些简单手段可以拿到这个密码才对。否则建立一整套管理系统成本实在太高了。
最近在家办公,遇到的第一个问题就是家里网络极不稳定,无法 git clone 那些庞大的仓库。我知道 git 现在支持浅拷贝,用 --depth 1 就可以取出某个分支的 HEAD 指向的拷贝所依赖的所有文件。
但是,光用 git clone url --depth 1 还不能解决我的所有问题。因为需要传输的文件还是太大,不稳定的网络无法坚持到我顺利下载完成就断开了。而 git clone 得下载过程似乎不能续传,我只好另辟蹊径。
过去翻 git 文档时,曾经了解过有一个 git bundle 这个指令可以对需要传输的内容打包,然后大多数依赖接受数据的 git 指令都可以直接接收用 git bundle 打好的包,而不必通过网络传输。事实上,git clone 的过程就是在远程打好包,然后传输到本地,再解开的。
首先,我们在 2011 年底开创的简悦被阿里巴巴文化娱乐集团全资收购了。原来简悦的全套班底转型为阿里大文娱游戏事业群。
当收购的事情尘埃落定,我发现可以从新的视角来看待未来,重新设计制作一款 3d 引擎这件事可以重新启动了。在简悦一直想做而做不了这件事,是因为没有余力,必须优先考虑产品盈利;而对于阿里来说,投入资源来做这样一件短期没有收益,但长远看来却很有意义的事是很自然的。
世面上已经有了很多优秀的 3d 游戏引擎,比如目前最为流行的 Unity 和口碑优异的 Unreal ,还有许多品质精良的开源引擎,再从头做一个又有什么意义?
我是这么看这个问题的。
Unity 和 Unreal 固然优秀,但是它们在设计之初并没有把移动设备作为核心平台来考虑。发展历史悠久,固然细节上的完善是后来者无法比拟的,但也存在很多历史包袱。尤其是移动平台上需要特别考虑内存紧致、节约能耗,更胜过运行的更快、效果更华丽。
另外,就国情而言,我们需要的移动游戏需要有更弹性的资源管理以及更新方案,这一直是 Unity 的弱项。Unity 作为一个闭源引擎,很难让使用者做出根本改进。
我们已经和 Unity 达成了合作,购买了全部源码。现在公司也成立了专门的团队自己维护 Unity 源码对其他产品团队做技术支持。在这种情况下,重新抄一个 Unity 没有意义:有什么需求,我们完全可以在 Unity 源码的基础上做开发。所以我要的是一个全新的东西。
这段时间玩 bgfx ,除了前段公布的 lua binding 外,还颇做了一些别的工作。
首先是帮 bgfx 的 directx 12 driver 打了补丁,使之可以用 mingw build 出来正确运行。也就是之前 blog 上提到的 Direct3D12 的接口设计 bug 。这个 pr 已经被官方接纳。
然后是我给 bgfx 的 debug text 做了中文的支持。 bgfx 专门做了一个层,模拟 VGA 的 text mode 。一开始我学着过去 dos 模式下做中文系统的方式增加了双字节支持,采用在模拟出来的 video memory 的 attribute byte 上设置几个特殊标记来表示接下来的两个 slot 是连起来的一个 unicode 字符。
这种让一个汉子占据两个 video memory slot 的方式在过去非常常见,不过弊端也很明显:容易产生半个汉字乱码问题,解决方案看起来比较 trick 。而且把汉字作为一种特殊字符来处理,而不是彻底解决 unicode 大字符集的解决方案感觉也很不美观。
接下来我花了一点气力实现一个更加通用的 unicode 方案:
至少要支持多个 code page , 并把原本就支持的 dos 字符集当作 cp437 ,而可以由使用者执行添加新的 codepage ,比如汉字所用的 cp936 。再将不同的 codepage 统一转换为 unicode 。我为多 codepage 编写了一个简单的查找 cache ,字形贴图管理的新模块。cp936 里用到 15 点阵汉字字形是从文泉驿黑体中导出的。另外为了更好的支持 unicode ,把 virtual video memory 里保存 codepoint 的单字节扩展为 3 字节,可以把单个汉字放在一个 slot 里。不过,为了排版正确,还是需要在 debug print 的 api 中检测到汉字就在每个汉字后保留一个空格,让单个汉子占两个英文字符的位置。
这个 patch 现在可以在 bgfx 里使用 ,不过尚未合并到主干。看起来作者也没有拒掉,目前还留在 open 的 pr 列表中。
这段时间玩 bgfx ,除了前段公布的 lua binding 外,还颇做了一些别的工作。
首先是帮 bgfx 的 directx 12 driver 打了补丁,使之可以用 mingw build 出来正确运行。也就是之前 blog 上提到的 Direct3D12 的接口设计 bug 。这个 pr 已经被官方接纳。
然后是我给 bgfx 的 debug text 做了中文的支持。 bgfx 专门做了一个层,模拟 VGA 的 text mode 。一开始我学着过去 dos 模式下做中文系统的方式增加了双字节支持,采用在模拟出来的 video memory 的 attribute byte 上设置几个特殊标记来表示接下来的两个 slot 是连起来的一个 unicode 字符。
这种让一个汉子占据两个 video memory slot 的方式在过去非常常见,不过弊端也很明显:容易产生半个汉字乱码问题,解决方案看起来比较 trick 。而且把汉字作为一种特殊字符来处理,而不是彻底解决 unicode 大字符集的解决方案感觉也很不美观。
接下来我花了一点气力实现一个更加通用的 unicode 方案:
至少要支持多个 code page , 并把原本就支持的 dos 字符集当作 cp437 ,而可以由使用者执行添加新的 codepage ,比如汉字所用的 cp936 。再将不同的 codepage 统一转换为 unicode 。我为多 codepage 编写了一个简单的查找 cache ,字形贴图管理的新模块。cp936 里用到 15 点阵汉字字形是从文泉驿黑体中导出的。另外为了更好的支持 unicode ,把 virtual video memory 里保存 codepoint 的单字节扩展为 3 字节,可以把单个汉字放在一个 slot 里。不过,为了排版正确,还是需要在 debug print 的 api 中检测到汉字就在每个汉字后保留一个空格,让单个汉子占两个英文字符的位置。
这个 patch 现在可以在 bgfx 里使用 ,不过尚未合并到主干。看起来作者也没有拒掉,目前还留在 open 的 pr 列表中。
前两年有同学给我推荐了 BGFX 这个库,第一眼被它吸引是它的口号:"Bring Your Own Engine/Framework" style rendering library 。这动不动就说自己是 3d engine 的时代,好好做好一个渲染库,仅仅做好渲染库,是多难得的一件事情。
今年国庆节的时候,偶然间我又翻到这个仓库,居然作者一直在更新。坚持了五年,一直在维护这么个小玩意,让我对这个项目多了点信心。节后我饶有兴趣的研究了一下它的代码。
现在我觉得,这个库的设计思想非常对我的胃口,核心部分几乎没有多余的东西:数据计算、平台 API 支持、数据持久化格式支持、等等都没有放在核心部分。它仅仅只做了一件事:把不同平台的图形 API :Direct X 、OpenGL 等等整合为一套统一的接口,方便在此基础上开发跨平台的 3d 图形程序。不同平台的 3d api 的差异,正是 3d 游戏开发中最脏最累的活了。
现在的 IM 在设计上是基于会话的,多个人可以组成一个会话,相当于一个聊天室,当一个人加入到一个会话后,就可以看到从加入开始之后这个聊天室里所有参与人的发言。有的 IM 会把两人对话也抽象成同一个东西,也可能出于优化的考虑把双人对话特殊处理。
所以,这些 IM 在操作界面上会有一个会话列表:表现出来会是联系人名单、聊天群列表等等。选中会话列表中的项目,进入会话查看聊天记录、发言,就是这类 IM 的使用逻辑。
我认为,这种对即时通讯的抽象方式,其实是不适合办公环境的。和日常个人社交环境不同,办公群体其实是一个相对关系密切的团体,我们通常不会拉黑一个同事不让他给你发消息,也不会拒收公司发的通告,也不会因为一个同事平常不和你打交道就拒绝建立联系。项目组里的讨论,也未见得是多么保密的事情,需要防止隔壁组的同事旁听。你也很少会在办公 IM 上和妹子私聊谈人生理想。
我们这几年使用腾讯的 RTX 作为公司办公使用,我就感受到了太多这类设计缺陷。比如,有同事找我有事,我忽略了他的私聊信息;找人一般在对方活跃的项目群组里吼;程序群沦为了日常扯淡的位置,常常同时讨论着不同的问题,线索及其混乱。“群”这个设计,我在很多年前就思考过 ,我一直觉得需要在根本上换个角度看待社交聊天的需求。
U3D 的打包流程,谁用谁知道。
由于输出 ios 包必须在 xcode 环境,跑在 Mac 系统上,所以为了定期版本打包,我们采购了配置比较高的垃圾桶来做。一台大约要三万 RMB 左右。
但我觉得这个方案的性价比太低了。
经过简单的考察,我发现,打包流程中最慢的环节是贴图压缩。在不同的平台,需要把原始贴图文件压缩成对应平台的压缩贴图格式: ios 平台对应的是 PVR 压缩格式;Android 平台对应的是 ETC 压缩格式,等等。
u3d 自己也意识到压缩贴图太慢,所以官方给出了一个 CacheServer 方案。
写备注总有时候光靠文字描述不是很清楚,这个时候特别想在文档中附个关系图。用 graphviz 的 DOT 来描述图固然不错,但是它需要额外工具来生成才能直观的查看。如果我们想在纯文本环境附上插图,使用 ascii art 是最佳选择。
我搜了一下,perl 的 Graph::Easy 是唯一能找到的支持 ascii 输出的关系图绘制软件。
但是这个东西有个问题,就是对中文支持不行,虽然文档中说完全支持 Unicode ,但显然作者并没有把汉字用在 Ascii 输出上过。
不堪被 windows 升级弹窗骚扰,终于升到了 windows 10 。最不能忍受的是新的中文输入法,之前用的智能 ABC 已经完全不能用了。btw, 我爹他老人家就是因为没有 ABC 完全输入不了汉字,又重装了系统,退回 windows 7 去了。我没那么能折腾,所以还是想别的招。
很多年前我就写过,为什么我需要 智能 ABC ,到今天观点还是没有变。我听说 QQ 拼音加入了 ABC 模式,其实就是加了 5 个笔画,它并没有理解 ABC 为什么那样设计,所以做的并不好。
并不是说 ABC 设计的多完美,如果我来设计我期望的中文输入法,肯定有很多想法和 ABC 的设计不同。但是其核心是一样的:那就是,赋予每个汉字更多的编码形式,结合词(不是句子)尽可能的减少重码。
我部署在 linode 上的这个 blog 是 09 年装的 ubuntu 系统。只在 10 年的时候升级到 ubuntu 的 10.04 LTS 版,后来就一直懒得升。
其实敲一行指令就可以了,可每次 ssh 上去就是懒得做。今天突然觉得不太妥了,试了一下 do-release-upgrade 居然失败了 :( 。google 了一下,大约是说我这个系统停止维护太久了,早就超过了最后期限,升不了了。
痛定思痛,打算亡羊补牢一把。我想了一下,其实最主要的业务就是一个为 codingnow.com 解析域名的 bind9 服务,一个 apache 一个 mysql ,重装一下系统的话,把数据链过来应该问题不大。正好 linode 前些年送了我 8G 硬盘空间,一直懒的用上,正好装新系统。
前两天成功用 mptcp 搭建好出国上 github 的快速通道后 ,在想如何方便的无缝使用。如果不使用 vpn 的话,就无法用路由规则来把流量倒向隧道。当然修改内部 dns 的 github 域名解析是可以的,但终归不是很舒服。
SA 试了一下用 PeerVPN 搭 vpn tunnel ,工作倒是正常,但是 mptcp 跑在隧道上等于是白费了。PeerVPN 是用 UDP 通讯的,实际上只走了单条路径,如果再在上面跑 mptcp 等于是自欺欺人。
所以也曾经考虑过使用基于 TCP 连接的 VPN ,比如 openVPN 。在 SA 尝试做配置的时候,我突然有了个想法。既然 PeerVPN 是开源的,何不修改一下实现,让它支持多个 ip 间建立多条路径的通道呢。
从去年开始,我们的工作项目逐步迁往 github 的私有仓库里。github 太好用了,自己搭建的 git 平台完全比不上。可是购买企业版本自己架服务器成本又太高(平均一个人一年要 250 刀),而我们项目并不多(只是人多)购买私有仓库绝对够用了,唯一的缺点就是 github 没有在国内开展业务,服务器都在境外,速度很慢。
之前我们无论是电信还是联通线路,从 github 上 clone 项目的速度一直没有超过 200KB/s ,而我们租用的国际线路本身带宽又很低(因为单价太高,所以只做部分翻墙用)。而且连接还不太稳定,有一定的丢包率。
考虑到我们办公室租有多条不同运营商的宽带,所以最近在考虑怎么把这些资源整合在一起使用。
带宽的瓶颈显然是在墙上,所以只要提高过墙的带宽就可以了。我在 linode 机器 上做了测试,从 linode 美国机房 clone github 仓库的速度轻易可以达到 8MB/s 。
一开始我的念头是自己写一个支持多条 TCP 连接协作的 tunnel 程序。后来转念一想,MPTCP 不就是干这个用的么?去年的时候玩过一阵 MPTCP ,这次和我们爱折腾的 SA 同学们一起再试试。
上次提到过 抵抗组织:阿瓦隆 的辅助工具的一个想法。主要是用手机帮助大家减少天黑请闭眼环节的繁琐工作。参加游戏的人只需要看一眼手机,就可以了解游戏局面。这样就不需要额外的主持人不停的叫大家闭眼,某某睁眼确认等等了。
另外,也可以简化投票任务这些环节(如果是杀人,那就是确认杀掉谁,指认谁等过程)。一旦去掉了额外的道具,我们就不再需要桌子来玩。可以方便的在饭桌上打发时间了。
我在 github 上创建了一个项目。初步的计划是做成一个 web 网站,当然以后改成手机 app 也可以(可以只需要一个 app 做 host,其他玩家还是继续用浏览器访问它,这样就不依赖互联网连接了)。
因为我几乎没有 web 开发的经验,所以之搭了个简单的框架,剩余的部分是同事参与来做的。目前之完成了进入房间分配身份的部分,进度比较慢。如果能有经验的同学加入会好一些 :)
我相信至少在国内的游戏策划圈, Excel 是每天必不可少的存在。倒不是因为要用它制作数值表格,一切文档最终都一定是用 Excel 写的。但作为一个程序员,我相当的痛恨 Excel 文件,就好像我当初痛恨 word 一样。只有几个字就不要保存成 doc 文件啦,可现在已经没有人用 word 了,大家全转去 Excel 了。如果有可能,策划一定愿意在单元格里写脚本的,这样可以将重点标红。
提取 Excel 中的文字信息并不复杂,但真正的麻烦在于 Excel 文件对版本管理工具是极不友好的。甚至你打开一次 Excel 文件再保存关闭,也会生成一个完全不同的新版本。这是因为,文件中记录了最后修改的时间(是的,Excel 不信任文件系统里的时间);还有激活的单元格是哪一个。在这种环境下,多人协作的版本控制工具用起来绝对是一个悲剧。
我大概花了一周时间来试图解决一系列问题。结果不算成功,也不算失败。这里记录一下上周踩过的坑。
问题源于我们的项目中,策划把一切他们能生产的东西都记在了诸多的 excel 表格里。当然,和上世纪的程序员一样,大家都尽量自己维护自己的那块文件,所以即使在版本管理工具下,也基本没有冲突。但是总有那么 1% 的机会,几个人会修改同一张表格的,尤其在项目压力大时,往往实现功能的程序也会打开表格对里面的数据做一些修改。在版本控制工具下,冲突就在所难免了。尤其是我们刚刚让策划从 svn 迁移到 git 下,git 的工作流的复杂性很容易让策划的脑子不够用了(实际上受 Excel 文件格式限制,他们也只需要一个版本备份工具,其它本来就是多余的)。我开始动念头来解决问题。
首先,xlsx 文件其实是一个标准 zip 压缩包,里面打包了一系列 xml 文件。如果仅仅是需要一个文本格式,那么只需要把包解开,用一种非压缩的形式重新打包即可。
对于一些嵌入的图片,只需要用 base64 编码。由于嵌入表格的图片多半不会修改,所以并不会造成版本间的差异。
一开始,我以为这项工作两小时就能搞定,事后发现,太天真了。
我写了一个 lua 的小程序,可以读出 zip 包里的文件,对文件名排序,然后按文件名/内容的次序依次把文件连在一起形成一个大文本文件(其中的2进制内容使用 base64 编码)。这样处理后,xlsx 文件基本就是一个文本文件了。为了对版本管理工具友好,我对 xml 里的标签后增加了适当的分行。这样处理以后,版本管理工具基本能识别出表格数据每个版本的差异。
第2步,可以动手消除一些对版本有影响却对我们没有意义的数据段。比如文件的最后修改时间、激活的单元格等。这样、如果打开一个 excel 文件,保存后就不会产生差异。
那么,这是一个新的文件格式。怎么让 Excel (或 wps 等兼容产品)打开它编辑呢?
虽然第一反应是给 excel 写一个插件。但我知道拿不是一两个小时可以搞定的。所以我选择了一条弯路。写了一个脚本,可以生成一个临时目录/文件,在用户想打开一个自定义格式文件时,先转换为标准的 xlsx 临时文件,让关联的软件(excel 或 wps 等)编辑它。我们可以监控这个文件的变更时间,来即使把临时文件转换回去。当这个临时文件可写时,就表示已经停止编辑这个文件了(excel 对打开的文件有文件锁定)。这时,可以删除临时文件。
让自定义文件格式关联到这个脚本(我用 lua 编写的十多行程序),策划就可以直接双击自定义格式文件编辑了。
我们的第一个手游差不多做完了,预计在明年 1 月初推广,目前内测的情况非常不错,我们也可以考虑开始下一步在手游领域立新项目了。
上个项目做的太匆忙,今年 4 月份才开始。因为决定做一个 2d 游戏,我觉得在 2d 游戏引擎方面我有超过 15 年的经验,使用一个流行的开源引擎,比如大家都在用的 Cocos2d-X 还不如自己写。这样对引擎的可控性更强,可以方便的定制自己需要的功能,并在性能上做针对性的优化。手机设备的硬件性能远不如 PC 机,即使程序性能足够,我们也要考虑硬件的能耗,让电池用的更久一点,让设备不那么放烫。优化引擎也是游戏程序员的乐趣之一。
我们这个项目还是做的太急了,只花了一个月时间做引擎,然后在上面做了太多应急的各种修改,到项目完成(10 月)时,已经很不堪了。我不想把这块东西带到下一个产品,所以打算重新把这块代码理一下。
开源是一开始就想做的事情,可以帮助到别人,也同时督促自己把代码写的更整洁。从这周开始,我满头写了一周代码,从头写了 4000 行代码,就有了这么一个项目:ejoy2d 。
当然它还很不完整,有兴趣的同学可以跟踪这个项目,我和我的同事会逐步完善它。同时欢迎其他同学推送 Pull-request 。下面对 ejoy2d 做一个简单的介绍:
最近两天是我们项目第二个里程碑的第一个检查点。我们的服务器在压力测试下有一些性能问题。很多方面都有一个数量级的优化余地,我们打算先实现完功能,然后安排时间重构那些值得提升性能的独立模块。
我最近两周没有项目进度线上的开发任务。所以个人得以脱身出来看看性能问题。前几天已经重新写了许多觉得可能有问题的模块。在前几天的 blog 里都有记录。
虽然没有明显的证据,但是感觉上,我们的服务器底层框架 skynet 有比较大的开销。这个东西用 Erlang 开发的,性能剖析我自己没有什么经验。总觉得 Erlang 本身代码基有点庞大,不太能清晰的理解各个性能点。
其实底层框架需要解决的基本问题是,把消息有序的,从一个点传递到另一个点。每个点是一个概念上的服务进程。这个进程可以有名字,也可以由系统分配出唯一名字。本质上,它提供了一个消息队列,所以最早我个人是希望用 zeromq 来开发的。
现在回想起来,无论是利用 erlang 还是 zeromq ,感觉都过于重量了。作为这个核心功能的实现,其实在 2000 行 C 代码内就可以很好的实现。事实上,我最近花了两个整天还不错的重新完成了这个任务,不过千余行 C 代码。当然离现在已有的框架功能,细节上还远远不够,但能够清晰的看到性能都消耗到哪些位置了。其实以后不用这个 C 版本的底层框架,作为一个对比测试工具,这半周时间也是花得很值得的。
我将这两天的工作开源到了 github 上,希望对更多人有帮助。从私心上讲,如果有同学想利用这个做开发,也可以帮助我更快发现 bug 。有兴趣的同学可以在这里跟踪我的开发进度 。
关于接口,我在上面提到的 blog 中已经列过了。这次重新实现,发现一些细节上不合理的地方,但是不太好修改,姑且认为是历史造成的吧。
在目前的版本里,我还没有实现跨机器通讯,我也不打算讲跨机通讯做到核心层中。而希望用附加服务的方式在将来实现出来。
这个系统是单进程多线程模型。
虽然现在 twitter google+ facebook (你也可以把前面的产品换成新浪微博,人人)已经成为网上公众信息交流的主流工具了。但论坛这一形式始终有它存在的价值。至少,在 mailling list 无法成为主流的状态下,产品在网上发布,大多还是需要一个类似论坛的形式为用户提供服务的。当然,google groups 本质上是一个邮件列表,它也把自己称为“网上论坛”的。我说的这个东西,应该大体上归类于 forum 。但 forum 这个词大多数中国人拼不清楚,大家更习惯称之为 bbs (我知道 forum 和 bbs 其实是有差别的)。
当年 ROR 正火爆的时候,有人说用 ROR 搭建一个网站只需要几行代码,没有更简单的了。有人回,不,用 Discuz 搭建一个论坛更简单。
以为然。
但是我始终不喜欢 Discuz 形式的论坛,尤其是它之后的发展。过于花哨繁杂了。我更喜欢 douban 小组那样的简单设计。只不过那个设计过于简单,如果单独抽出来做为一个产品,对于我有许多信息过滤的需求无法满足。
对于为某特定产品服务的论坛,比如为特定网络游戏的用户服务的论坛,我构想的形式大约是这样的。
首先不需要分板块。对于集中话题,按时间整理出信息流就足够了。
我一直不太满意 google protocol buffers 的默认设计。为每个 message type 生成一大坨 C++ 代码让我很难受。而且官方没有提供 C 版本,第三方的 C 版本 也不让我满意。
这种设计很难让人做动态语言的 binding ,而大多数动态语言往往又没有强类型检查,采用生成代码的方式并没有特别的好处,反而有很大的性能损失(和通常做一个 bingding 库的方式比较)。比如官方的 Python 库,完全可以在运行时,根据协议,把那些函数生成出来,而不必用离线的工具生成代码。
去年的时候我曾经写过一个 lua 版本的库 。为了独立于官方版本,我甚至还用 lpeg 写了一个 .proto 文件的解析器。用了大约不到 100 行 lua 代码就可以解析出 .proto 文件内的协议内容。可以让 lua 库直接加载文本的协议描述文件。(这个东西这次帮了我大忙)
这次,我重新做项目,又碰到 protobuf 协议解析问题,想从头好好解决一下。上个月一开始,我想用 luajit 好好编写一个纯 lua 版。猜想,利用 luajit 和 ffi 可以达到不错的性能。但是做完以后,发现和 C++ 版本依然有差距 (大约只能达到 C++ 版本的 25% ~ 33% 左右的速度) ,比我去年写的 C + Lua binding 的方式要差。但是,去年写的那一份 C 代码和 Lua 代码结合太多。所以我萌生了重新写一份 C 实现的想法。
做到一半的时候,有网友指出,有个 googler 最近也在做类似的工作。μpb 这个项目在这里 。这里他写了一大篇东西阐述为什么做这样一份东西,大体上和我的初衷一致。不过他的 api 设计的不太好,我觉得太难用。所以这个项目并不妨碍我完成我自己的这一份。
鸟巢一线,起步的地方很吓人。将近 2 米的间距,需要人从 7,8 米的深坑上空扑过去。虽然不太危险,但需要爬的人克服一点心理压力。我们觉得做一个绳梯把旁边的大石头和岩壁连起来。
自从上次锯掉树桩后,我们又花了一天时间清理线路。还有一些小树,杂草要除掉。工作不比头一天锯树桩轻松。在半空挂了几小时怪累的。
然后就是测量工作。我们决定做四段绳梯,把可笑岩壁下方大仰角都接上梯子。自然岩壁就这点不好,难度不由人控制。这块岩壁本身是很漂亮的。但是下段实在是太难了,基本没有几个人能爬。而上段也就在 5.9 左右。爬得上下段的人,上面索然无味。而上段给初学者或是大菜鸟如我这样的,倒是非常合适。
绳梯是个很好的方案。甚至以后家属来围观也可以玩玩。梯子上可以挂快挂做保护,也很安全。爬上 7,8 米的梯子去到半空,也是难得的体验。
我们花了 300 多块买了 67 斤的尼龙绳,很粗的那种,一捆有 300 多米。高强给出了一种结梯方案,我在 youtube 上找了另一种。在家用帐篷绳子先试了一下。
这两天一直在圈人一起玩 google+ 。由于众所周之的原因,在墙内推广这个东西阻力重重。还好不需要必须翻墙,google 在北京是有网关的,修改本机 hosts 文件,把相关的域名指过去即可。在这里就不列出方法了,希望下面的评论中也不要贴出来,私下交流即可。还好移动版 G+并没有封掉,究其原因可能是 m.google.com 是所有 google 移动服务的统一入口,如果封杀影响较大。而 https 协议让墙无法分析 url ,不可能做到部分干扰。如果有一天真封禁了,手机上都无法阅读 greader ,收取 gmail ,那还真是个悲剧。
我在拉我老爸玩 G+ 的过程中,他老人家反应了一个问题,家里用手机使用 android 的 app 发不了帖子。我估摸着可能是被墙了。虽然可以让他 root 掉手机修改 hosts ,但显然这不是一个简便的解决方案。我便着手远程登陆家里的网关。那是一台用 LinkStation Pro 改造的 linux debian 机器。拥有一块 Arm9 CPU ,在上面跑一个 DNS 服务,足以让家中的局域网解析到可以登陆 G+ 的 ip 地址。
一条毛巾,它解释说,大概是对一个星际漫游者来说最有用的东西了。从一个方面看,毛巾有着巨大的实用价值:但更重要的是,毛巾有着巨大的心理学上的价值。也不知道出于什么原因,如果一个“正常人”(正常人:非漫游者)发现一个漫游者随身带着毛巾,那么他会很自然地认为此人同样也有牙刷、浴衣、肥皂、装饼干的罐子、保温瓶、指南针、地图、绳捆、灭蚊喷剂、雨衣、太空服……等等。于是乎,他会很乐意借给这个漫游者所有这些东西,甚至还有其他的许多东西——而这些东西通通是这个漫游者碰巧“丢失”了的。这个正常人的心理就是,一个人,在广阔的银河系中漫游,在面对了许多可怕的困难并且成功地战而胜之以后,他如果仍然还弄得清楚自己的毛巾在哪里,那么这显然是一个值得认真对待的人。
—— 《银河系漫游指南》
下降并没有我想象的简单,尤其是长距离分段下降更是麻烦。
每一段,我们需要小心谨慎的下。如果绳子抛的不好,沿路都需要整理。高强比我下的快,所以大多数时候都是他在整理下方的绳子。鉴于我出了点小事故,我们换了绳。我用那根旧一点的,摩擦力比较大,好控制一些。每到一个保护站,我都长嘘一口气。更换保护点,然后示意小鬼下来。等他下到一起时,再费力的抽掉绳子,整理,做系统,准备下一段。
杭州到仙居的高速上没有什么车,路也修的相当好。高强开车,全程都没有一丁点超速。这么好的路况都不稍微开快点,很不可思议了。我们在路上闲聊这个话题。高强说道,他有一次在高速上差点送命,车都开到前面大货车车底了,就差那么一点点。事后总结教训,总结了 10 多方面,有三个主要错误,其余都是次要问题。其中超速就是主要错误之一。任何一个主要错误不犯,车祸就不会发生;而如果那些次要问题如果回避了,也就不会那么严重。可见要命的小概率事件都是无数人为疏忽累积起来的。遵守前人制定的安全规范那是相当的重要。
第 5 段爬的很简单。为了节省高强的精力和体力,小鬼决定用上升器上,我继续爬顶绳,附带收一部分快挂。因为即使有上方的提拉,主要还是得自己爬的。岩壁上的快挂可以作为大手点使用,爬起来轻松一点。大烟囱爬起来很费力,到上端变窄后稍容易一点,可以用背顶着。但我一转换角度,就漏收了一把快挂。好在我们带有多的,也不碍事。
第 3 段的难度不算太大。5.9 。只有起步稍麻烦。不过我手指受伤,已经顾不得许多。我在下方收保护站的时候遗漏了一条扁带,懊悔不已。幸亏这次有带多的。唉,毕竟是经验不足。
小鬼教我抓快挂的上法,还特地在难点延长了快挂。我的左手指着不上力,不过抓快挂还是可以上的。加上高强在上方用滑轮拉我借力,很快就翻到外侧的 face 面。
爬 Face 面很爽,暴露在半空中的感觉很刺激。这一段有点向里俯角,所以如果技巧得当,基本不用手指的力气,全靠手掌撑起,腿部用力。2 个小时后(11 点半),我们就全部安顿在了第 3 保护站。
攀岩是一项事故率非常低的运动,甚至远低于我以前玩的自行车。因为各种器材和绳索在出现意外的时候会牢牢的保护住你。
我们这次玩的运动攀的安全系数又高于传统攀。因为挂片是事先用膨胀螺栓打在岩壁上的。这倒不是说用岩塞不牢固,只要技术上不出错,岩塞是绝对信的过的。但由攀登者自己放保护点,总没有事先开线人仔细选择的保护点绝对安全。
结组攀登属于技术要求比较繁杂的了。需要掌握更多的器材使用,绳结的打法。需要更多的野攀经验。不过,只要严守最基本的一些安全操作守则,至少,是不会有生命危险的。最重要的,任何时候,要确保身上有至少一个保护。
虽然我很热爱攀岩运动,但一直水平很菜。直到现在都没爬过先锋。顶绳也就能爬个 5.9 的难度,勉强可以过几条 5.10 的线。所以这次高强叫我去结组攀爬天柱岩的时候,我是一点信心都没有。不过还是很兴奋的,只是担心拖累了大家。
嗯,就是这座山峰。恐怕是国内最长的运动攀线路了。共有 7 段,总长 230 米。若是再长点,恐怕就得带吊帐睡岩壁了。
Day 1 ,2011 年 6 月 28 日 周二
上午我还在睡觉,高强给我发了条信息,说是一起去天柱岩结组攀登。我那点破水平高强最清楚了。我自己没信心,不过他说我能上,那就能上。看了发过来的链接,极其动心啊。
今天在 greader 上看到这么一篇,用 DNS 隧道实现免费上网。我的思绪猛然回到去年去新西兰度假的日子。
有那么几天,我们在惠灵顿的海边山顶租了个屋子,一切都很舒服,但是不能上网。甚至于附近连 wifi 信号都收不到,想"借用"一下别人的 wifi 热点都不成。我顶着海边的狂风在院子里竖起天线,捕捉着周围微弱的信号,最终未果。然后转战屋里的有线电视。我发现和国内的有线电视一样,机顶盒是接有网线的。也就是说,物理上,存在一条链路接入了互联网。但是我插上电脑后,发现 ip 包根本发不出去。不过,好似有个 DNS 服务是可以用的。
当时也没多想,只是觉得有办法可以利用一下。不过隔天就搬走了,没有深入下去。今天回味一下,感觉的确可以利用 DNS 服务和外部建立连接。当然,一开始就需要在外界把接应的程序程序搭建好。
用 linode 有一年多了 ,除了架设 blog ,我也折腾点小程序放在上面跑。在互联网上有一台自己的主机,对于一个程序员来说,还是很有必要的。当然这 vps 绝对不能选国内的,原因你懂的。这样,附带的一个好处就是可以用 ssh -D ,相信许多同学都喜欢用。
没来由的,我想自己写一个小程序,完成 ssh -D 一样的功能,不过,不走 SSL 加密。当然也不能走明文,由于众所周知的原因,明文通讯很容易引起奇异的连接断开或长期超时的 bug ,此 bug 绝对不在于你的程序。网络连接永远不是 100% 可靠的嘛。
我花了两天实现我的构想,本来第一天已经完成了,但实现的过于复杂,且 bug 重重。花了一个通宵都没完全解决。在补了个好觉后,我在梦中意识到,应该简化方案,然后在第二天重写了一遍,终于可以跑起来了。代码是用 Go 实现的,比较玩具,quick & dirty 。不过我还是把它们放在后面。有兴趣的同学可以拿去改进。目前这个雏形已经够我用了,所以即使有改进或许也懒得再贴出来了。
最近闲了下来。断断续续的再想,如果业余时间弄一个开源项目玩儿,什么是比较好的题材,适合自己来做。想来想去,3d engine 是一个比较好的选择。以我来看,对外开源如果要吸引到足够的有经验的同学参加,必须项目有一定价值。要可以迅速的搭建工作环境并直接看到结果,这样才能有兴趣迭代做下去。起步必须自己一个人来做,东西得有个雏形。所以必须是自己比较熟悉的领域。
若论熟悉,其实游戏服务器的架构和实现,我这些年考虑的更多,也做的更多。但这个东西不适合做成开源项目。因为受众太小(不是每个人都有机会和意愿去架设网络游戏服务器的),而且它不能单独运行看到结果。没有玩家的游戏服务器是没有意义的。
3d engine 这些年也有在开发。但是公司不可能允许开源已有项目。如果想玩儿,从头做是唯一选择。而且重新开始有更多的乐趣,再造轮子原本就是程序员们的欢乐源泉之一。如果自娱是唯一目的的话,就不必过多考虑商业引擎必须考虑的问题。比如兼容更多的底层 3D API ,做全平台兼容,支持低端硬件等等。甚至于还要去考虑日后防外挂等无聊的问题。
这个月做了不少杂事。记个流水帐总结一下。
梦幻西游的 Client 需要优化,我之前提了个方案。对 2d engine 的底层库做了些小修改后,大部分工作都是同事在做。最后完成后,说是性能提升到了可以接受的程度。
我抽了好几天时间研究 XMPP 协议。这个前两年看过,不过这几年开源界内容增加很快。因为对 lua 有偏爱,所以着重阅读了 Prosody 的源码。设计的不错,很容易读,量也不大。
因为对有道词典的 Chrome 插件的一个 Bug 有所抱怨。认识了做维护的同学。我把我自己对 bug 的 patch 提交了。就是个 js 的小程序,读起来也就是几分钟的事儿。嗯,在听取意见这件事儿上,有道的同学的态度比泡泡组的同学好多了。
我们一合计,就合计到另件事儿上了。想做个 XMPP 聊天群。当然了,想法早有,就是没实施罢了。花了几天,用了 prosody 和 xmppy 把个机器人整了出来,可以群聊了。不过这兴趣后来也就过了。
我的那个 Palm Treo 650 终于寿终正寝了。去年曾经买了个 HTC Hero 送老爸,玩过几天 Andriod ,还是有点好感,这次打算选一款 Andriod 系统的。
曾经也考虑过 iPhone 或是 Palm Pre ,请教了我公司的手机大神,大神同学说,他买过两款 iPhone ,用一段时间总想换,不推荐长期使用。至于 Palm Pre ,大神同学也买过一个,评价是极其垃圾,完全比不上 Treo 系列。他最近半年买过 Milestone ,Desire ,Nexus One ,X10i ,i9000 等等几款,每个都有不同的缺憾,最终比较下来,给我推荐了三星 i9000 。
我比较信任亲身使用者的感受,尤其是对手机如此挑剔,以至于每一两个月就情不自禁的买新手机的同学的现身说法。没太多犹豫就去 taobao 下了单。
结果…… 等了 8 天还是没寄来,卖家一直说缺货。昨天忍不住退了款,还是很干脆的。再一看,原来是涨价了,从 3450 涨到了 3600 。换了一家重新下单,今天一早就寄到了。
最近几天,我的几台台式机的 Ubuntu 都顺利从 9.04 升到了9.10 。在这里继续表扬一下网易以及负责的同事,mirrors.163.com 的源在我们这里相当快,可以轻松达到办公室的出口带宽峰值(1MB/s)。这样,升级的时间长短就取决于 cpu 的速度了。
周末,我计划有两件事。
其一,有个程序想写;其二,升级我的本的 Ubuntu 系统。
昨天犹豫了一下,做了个正确的决定。先把想写的程序写完,今天再来折腾本本。果然,这是个明智的决定。否则,一天若是搞不定,会坏了心情,程序就没得写了。
担心的事情终归是要发生的。我的预感没错,这次升级又折腾了我一把。记录下来,有 sony vaio p 的用户搜到这里,希望我的记录可以给你们帮助。
我的本配的 Intel 板载 GMA500 的显卡。当时选机器的时候就考虑过显卡因素,性能不重要,但是驱动要支持 opengl 2.0 ,这样至少我可以在笔记本上有限的调试下程序。wikipedia 上说 GMA500 支持 Opengl 2.0 我就信了。
拿到机器后,很是一阵折腾,把 Linux 下驱动装好。果然可以查询到 Opengl 2.0 ,不过支持的不算太多,或者说我们的程序没有彻底的测试,有些写的不规范的地方,不是那么顺利的可以跑起来。还需要慢慢改。
Windows 下是彻底看不见 Opengl 了。有点不甘心。
我一直不用笔记本的。因为不想背着个累赘到处跑。笔记本的键盘也用不惯,屏幕不舒服。前段时间,一个同事颈椎出了点毛病,据说就是用了几年笔记本给闹的。确症后买了外接键盘,在办公室也外接显示器用。
如果不是近期需要出差比较长时间,而且还需要在出差期间写代码,我是不会动这个念头的。
挑了几天后,决定买 Sony 的 Vaio P 系列。比较了一下,发现国内行货的 CPU 比较慢,而日版的 P91 可以升级到 Z550 ,有 2GHz 的主频。(不过 Atom Z 系列终归是好不到哪去,只能快一点是一点了)最终决定找人从日本代购。
这两天在我的 LS Pro 上装 BT 软件。以前我在 freebsd 下都是装的 ctorrent ,这次想换个别的。看中了 RTorrent ,项目维护还比较勤,新版支持 DHT 。不过 debian 的源上比较老,官网上那个源我连不上。所以就下源代码自己编译了一个。
原来以为这种小东西没多少代码量的,本地编译就够了。可惜我轻视了 C++ 代码编译的龟速。在 LS Pro 上,居然一个短短的 .cc 文件就要编译 20 秒左右。有点后悔没有用交叉编译,不过忍了几小时也就过去了。
新版本支持 xmlrpc 的控制协议。我就可以装一个 web 界面管理了 :) 我选的是 rtgui 还不错。
本来以为一切都搞定可以庆祝了的。没想到试了一个种子,其中中文文件名出现乱码,连带的导致了 rtgui 工作不正常 :( 然后花了一整夜的时间来折腾这个,好不辛苦。
本文写给搜索引擎过来的朋友,我估计还有人会跟我一样的想法:把 Link Station Pro 刷机,改成一 ADSL 拨号网关用。
话说,前几天,我按这个帖子的方法,把我的 Link Station Pro 刷到了 2.6.26 的内核。本以为某人已经帮我编译了强大的内核,想怎么玩都够了。
今天试了一下安装 pppoeconf 打算让 LS Pro 自己拨号,这才发现,这个 kernel 里居然没有编译进 ppp 的支持。google 了老半天也没人弄一个出来。大郁闷。
本者自己动手,丰衣足食的原则,我决定自己 build 一个 kernel 出来。
国庆打算回武汉。长假里得找点东西折腾着玩玩。所以就在网上订了一台 LinkStation Pro ,250G 的版本。准备刷了机做服务器玩。这台 NAS 性能不错,有 400MHz 的 Arm9 CPU ,128M 内存,和一块千兆网卡以及两个 USB 口。最关键是能耗低,才 21w ,没什么噪音,可以 24 小时开着。
下订单之前,用 google 好好做了下功课,确认可以装 debian 就放心了。这周到货之后,这两天晚上一直在折腾这个小玩意。
不过真正刷机时没想象的那么顺利。
新来了个同事,用 Linux 做桌面的。这样也好,可以节省一套 Windows 的费用。买组装机即可,同样价钱可以比 DELL 的配置好上许多。
昨天装的机器,一开始遇到点小麻烦,Ubuntu 7.10 对板载网卡 RTL8111/8168B 支持有问题。显示是安装一切正常,但是就是网络不通。ip 包发出去似乎就消失了,收不到回应。奇怪的是,Ubuntu 7.04 下却一切正常。google 上没有找到解决方案,也懒得细查,抽屉里翻出块更老的网卡装上。btw, 上次装 Solaris 10 ,这块板载网卡也是不认的。
接下来是显卡的问题,板载的 Intel 945 的显式芯片,按道理 3d 性能还是不错的。可惜 3d 这部分,一半靠硬件,一半靠软件(驱动)。怎么折腾都没找到 Ubuntu 下的对应驱动。
我装的 insight 是 6.3 版的,在 mingw 官方网站就可以下载 bin 安装包,用起来也非常方便。
可惜 gdb 的 6.3 版在 windows 下 attach 到一个进程调试时总是不对。如果在代码里写上 int 3 制造一个调试中断。中断发生后,再启动 insight attach 到出错进程,看不到被调试进程正确的堆栈。这一点让我非常郁闷,每次调试程序都必须用 insight 或 gdb 来引导,而不能像以前用 VC 那样,出错了再启动调试器。