盗賊の極意

Feed Rss

记录一下最近的工作收获

1. 去年用chrome devtool extension给公司的页游做了一个辅助开发工具,结果一年来除了我都没人用= =。直到最近被engineer leader重新挖了出来,组内推广了一波,用的人多了一些,给发了个月度最佳工程师提名奖励(没入选T_T),感觉很棒。
其实这东西本身超级方便我调试bug(我在组内主要任务就是追踪各种难以解决的bug),所以我一个人用我也挺满足的。但有别人也开始用我做的东西而且非常满意,这种感觉还是挺爽的,漫画家收到鼓励的读者来信时大概也就是这种心情了吧。

2. 我开发了大半年的一个 ios / android 照相机应用核心库上个月实际投入使用了。首次上线应用的晚上我负责去公司参与值守。虽然这种事主要是靠服务器端,我客户端开发在场也没法当场修补程序,但当晚还是有一些收获的。因为这个功能是在动画播放的时候让用户用app开摄像头拍摄动画,然后app判断你现在是不是在看动画首播直播,是的话就发个奖品,所以动画开始时twitter上有爆发式的关于本功能的留言。负责算法设计的顾问在里面挑了几个称赞我们黑科技的留言,我看了有点感动。这也是一种类似于收到读者来信时的心情吧。
从第一个hello world到现在,我写程序已经10多年了,但至今为止都是在享受一个人解题的乐趣。在第一家游戏公司,因为做的游戏比较小众,我自己也不玩,所以没有在意过玩家反馈。在现在这家公司,总算参与到了日本顶级手游项目,但这次是因为我一直在做的是偏底层的开发和疑难bug追踪,没做过什么大部分玩家能感受到我的存在的工作,所以也没有什么我的作品有读者(用户)的感觉。因为底层代码和bug追踪本身都是对我来说比较有趣的工作,所以我一度以为我是不在乎用户鼓励的冷面工程师。但经历过最近的几件事以后,我还是不得不承认,有人在使用、在期待着我的程序的感觉,真的很美好,令人沉迷。

3. 亲人离开研究机构独立创业,期间我除了帮忙写程序老本行以外,还有申请域名邮箱、关联主机、做简单的首页,上周又帮忙给他们买来放在家里的服务器设计内网拓扑结构(其实就是把这台服务器和家里自用的局域网分割开来,防止主机被黑导致家庭局域网沦陷),开机启动sshd,开端口,创建账号给合作创业者使用等等。虽然都是简单的基础设置,但对不懂这些的家人来说真的是帮助非常大。

4. 为了确认编译好的release版apk内的各种api网址用的是production而不是develop环境的,领导让我反编译了自家的apk看看里面。我说每次出新版apk都要找gui工具手动反编译apk然后搜索这些网址字符串是否存在,这种重复工作咱们还是写个脚本自动化吧(潜台词是不要让我们enginner做这种无聊的重复性体力劳动),于是我花了两天读了一下 zip 格式android 的 dex 文件的格式以后,用nodejs的zlib解压apk,找出classes.dex,再解析classes.dex ,找出所有的字符串,最后在这些字符串中查看给定的 production 环境的 api 的 url 字符串是否存在。要自己用 zlib 解压 apk的原因是如果想使用其他开源的解压zip的库的话要向上层层申请,非常麻烦,最后跟领导合计一下反正也就1天的工作量,干脆都自己实现好了。
这个工作中我最满意的是自己用第一手资料解决了问题。之前自己读HTTP的rfc徒手写 http proxy server 时也是,读文档能力是最重要的。不过当时我看的rfc是别人翻译的中文版... 毕竟原版300多页英文,考虑到开发效率,还是偷懒看中文了 =w=

太久没欲望,就容易懈怠

能激起我奋发向上热情的事不多,其中,身边人的成功算是比较有效的一个。

image from http://sc-pj.com/shitto-seiko/

今天去老朋友笃志的博客看了看他的近况,依然是每日工作在技术挑战中,依然是注重着身体健康,变化的,是那不断攀升的薪水。

我从大学时代就对笃志提及的游戏行业薪水充满向往,这算是坚定我入行信念最大的几个原因之一。

之后我求职不利进入小公司打拼,虽然学到很多,但对低薪和没有加薪可能的不安让我在学到能入手的几乎所有知识之后迅速下定决心跳槽,最终误打误撞来到现在的某日本本土手游大厂。

回过头来评价当初那段时间,我对自己及时果断的跳槽决定感到满意甚至感激。毕竟对我这样一个不喜欢冒险,安于平静稳定的技术工作的人来说,下定决心切换身边的生活环境并不是一件简单的事。

如今,我已经在现在这家大厂工作两年了。我很庆幸获得上司的赏识,帮我推掉重复性的体力劳动,让我专门负责各种技术密集的工作。可手游,尤其是页游方面能涉及到的技术密集型工作实在是非常有限。有些周期性出现的技术性工作做久了对我来说也变成重复性的体力劳动了,可对其他人来说依旧是无法接手的困难,结果就是我的工作中重复性工作也渐渐增多,只有在被外借出去帮别的项目开发核心功能时才有机会重新接触一些新知识。这样无法提升自我的工作内容,如果放在原来的小公司,我一定是会以跳槽来避开的。可在这家公司,为什么我却没产生跳槽的冲动呢?

我说服自己接受这样清闲的“退休生活”,把技术追求留在回家以后。可没有跳槽的压力,我连回到家的学习动力都没有了,回家以后也是一事无成。

 

除去害怕改变环境等可以被克服的心理压力外,落入这样被动的窘境主要是因为,欲望被满足了

 

今天看过笃志博客后重新燃起的欲望之火,我要好好培养

最近被一个android大量数据计算过程的提速问题困扰了一个星期,在尝试了各种办法之后,最终拜倒在了GPU的强大运算力面前。

 

我尝试过的实现一共有三种。

1. 平铺直叙的单线程java实现

这个主要是为了快速实现逻辑,用来检验代码正确性的,效率不是他需要考虑的问题,所以慢一点我也没什么意见。

 

2. jni调用C++,越过JVM,在native层实现运算逻辑

一开始实现完发现比java版快了10倍,顿时对native的效率赞叹不已。但之后总感觉哪里不对头,因为我记得java比C++只慢一点点,差距绝不会是一个数量级那么多。

后来检查发现是实现有误,纠正后整个运算竟然比java版还稍微慢了一点点。原因可能是java版里使用了android自己的jni版RGBtoHSV函数,而我无法从NDK平台直接调用android内置的实现,所以找了一个native版的实现,这个实现比java版慢了。

不管怎么说jni比java慢还是太反直觉了,可是用android-ndk-profiler测了一圈也没看出什么异常来,似乎纯粹的数字运算就是要耗费这么多时间。

这里需要强调的是,我的整个运算过程只调用了一次jni函数,慢不是因为频繁的跨语言通信导致的。

 

3. 借用GPU的力量进行运算。android平台强大的renderscript

实在不行就试试GPGPU这招我一开始就想到了,但是没想到实现起来会这么方便。这里真的要给android平台点个赞。

说来惭愧,游戏行业从业三年,我的3D编程能力还仅停留在对照教材实现示例的程度。本来这次都做好了3天入门OpenGL的打算了,没想到android自己内置了直接使用GPU的能力。启动运算传递数据的过程都可以直接从java中做到,我只需要额外学一个用来在GPU中执行的renderscript文件的写法就可以了。而这个renderscript语法类似C语言,比swift还好学啊。

renderscript最大的坑在于从出现到现在写法有变动。本来指导教程就少,里面还有很多已经变成了错误示范,无形坑人,最为致命。在跨过了这些教程坑以后路就平坦多了,业务逻辑的移植和结果验证一天搞定。

需要注意的是,renderscript本身并不保证一定会使用GPU,老版本的android好像只会用多线程CPU实现代替。不过我们项目的目标平台API LEVEL够高,不用太在意这个问题。

还有一点要说的是,renderscript目前只能做互不相干的大量运算,而像累加求和啊求最大值最小值之类各个运算结果之间会互相影响的密集计算要等android 7.0(API LEVEL24)以后才能支持,而且直觉上来说也不会有纯粹无关的运算那么快,不能过高估计他的效率。

 

以上,android版的优化总算是有惊无险的完成了。之后要研究iOS平台的同类问题,可能还会再写一篇总结。

其实我已经稍微调查了一下,遗憾的是iOS上似乎并没有android的renderscript这么方便的GPGPU支持,那到头来我还是要去入门一下OpenGL了,唉。(咦?我怎么还有点小高兴?!)

 进了一家本土手游大厂,技术受到领导认可,被安排专门处理日常开发之外的一些微科研性质的工作,每月加班时间不到10小时。

在据说是页游史上销量之王的项目组担任一个除我之外公司内无人可以胜任的闲职,除了偶尔帮忙调查一些复杂bug以外,大部分时间工作不饱和。

10年前决心进入游戏行业时,我会想到未来自己竟会对现在这种处境感到满足吗?

在专业领域,我最讨厌的处境是“技不如人”。研究生时代在众神之间自卑到焦虑,工作后来到技术水准严重低下的环境中,竟成了佼佼者,开始自满了。

我现在这样进步全靠自学的状态,想必也是大多数人的工作处境——只能在舒适区活动。
那研究生时代被扔进大神堆里比较有助于成长吗?其实也不是,完全不是。现在回忆起来,那是一个完全的惊恐区,我和他人之间的差距大到我完全想象不到要经历怎样的训练才能和他们站在同一高度。留学时代,我增长的最多的是视野的高度,让一直活跃在井底的自己知道,之前给自己设置的最高目标其实是低的可笑。
让我技术增长最多的,是在学习区“活动”的日子。“活动”可以是写代码,可以是读协议,可以是使用工具。

再来比较我现在的处境。我每天都有在工作,所以工作量是有的,但我感觉不到自己有继续在高速成长,因为用的都是已经相对熟练了的技能。
为一个项目修修补补,锻炼的不是我写代码的能力,而是在庞大的项目代码中寻找关键逻辑的能力。在这一年多的时间里,我漫游项目代码,寻找关键逻辑的能力确实得到了锻炼,但渐渐的,我发现我能更快找到问题的症结不是因为我阅读陌生代码的能力增强了,而是因为我更加熟悉现在这个项目的代码了。
这就很悲哀了。毕竟现在的项目总有一天会结束,那么我习得的这些关于这个项目代码结构的知识也将变得毫无价值。注意,漫游项目代码并不让我获得设计类似架构的能力,至少是帮助十分有限。因为我每次都是在寻找框架中某个非常具体的底层逻辑,并不是在很高的抽象层次中统揽全局。

现在我基本可以确定日常的工作内容对我的专业技能提升速度接近为0了,那我要怎么应对呢?

首先,我在工作范围内,寻找新的工作内容。因为我的岗位的特殊性,基本上日常开发外的东西我都可以参与,所以我可以为美工和测试人员开发和改良他们的工具。这个工作有些我已经在做了,有些我已经预约下来了,这是我接下来一段时间最期待的工作内容了。

其次,我真的非常渴望在工作以外的环境中,尝试从0开始搭建整个游戏客户端服务器端包括之后长期运营更新的整套架构设计。
做得好不好,最好的测试时发布给玩家玩,这就需要整个项目有足够高的完成度,也就是说,这个项目需要是一个团队项目。
参与别人的项目也是可以的,不过要找一个技术水平适合我,至少是要在我之上的业余游戏团队,还是很难的。我在qq群贴吧论坛微博上到处寻找过,结果并不乐观。

自己做项目我最担心的是我没有项目管理能力,也就是项目很可能做到一半就坑了。
业余项目中我认识的最有PM能力的是《四叶妹妹》和《即使如此小镇依然转动》等漫画的翻译组织者“三角”。那种有他在项目一定能完成的安心感和从不会责怪讽刺组员,让组内始终保持和谐的领导力让我对他充满了好感。可惜我自己这里八字没一撇,之前在他那里翻译漫画交稿效率也不高,没有足够的说服力拉他来做游戏开发的PM,可惜。(然而我不会放弃的!)

没有PM能力,没有PM,怎么做?
我能想到的一个办法就是先做些小到不需要PM就能做完的小项目,积累对个人项目成功完成的信心,然后逐渐扩大下一个项目的规模。
这是此刻对我来说最具可行性的方案,但,我还有一个小问题,就是眼高手低,不屑于做小游戏(汗)。不过和上面那些做大项目没有PM力没有足够的热情支撑跨日持久的业余开发等问题相比,不屑于做小游戏这个小问题已经容易对付的多了。

就做小游戏吧,从模仿现有小游戏开始。

回想一下自己当年学做j2me小游戏时的劲头吧,一个个小游戏的项目名我可是从0001一路做到了0012呢,大概。
我会被9年前的自己比下去吗?哼,开玩笑。逆风?看我翻给你看!

开个 swift 的系列贴先。

自己的活,经常做到只差一口气了,却对这个活产生了抵触情绪,就是不想做,十分抵触,严重时甚至能激起生理上恶心想吐的感觉。

最开始观察到这种症状是在研究生时代,我虽然非常想搞好研究报答教授,但真的是无论如何都无法开始阅读论文,也不能进行任何和自己的研究课题有关的活动。即使我痛苦的流泪,在地上打滚,却依然不能让身体和大脑按自己的心愿行动。所以我的研究生时代非常的痛苦。

第二次被这个症状伤到,是我加入了大学的游戏社团,担当了其中一个游戏项目唯一的游戏程序员时,在开发的最后阶段,我突然陷入了这种不愿意工作一心想逃避的状态,也是非常的恶劣。结果我害得这个游戏项目拖了5年没有完成。现在主创成员硕士都已经毕业了,我感觉非常的内疚,但依然无法驱动自己去为此工作。

我可以自豪的说,在我专注时,我的学习效率和工作效率都是业界顶级的。但我不得不面对的是事实,能否进入专注状态并不能由我的主观决定。

至今为止,我都借助兴趣带来的专注力来学习和行动。这种借力方式帮助我取得了相当高的成就。但帆船总不能逆风而行。在我的兴趣消失的时候,那种超人般的能力和天赋也会随之消失。

我曾经尝试过压抑兴趣消失时的抵抗状态,强行执行高强度的学习计划——每天背单词12小时以上,结果只坚持了两周,计划就彻底崩溃了,而且之后再也没能重启那个背单词计划。

为了找到适用于我的解除抵抗状态的方法,我回忆了一下过去的几个成功案例。

首先是备考留学考试。当时是每天泡在自习室里看书做题,生活单调但有规律。一旦生活进入规律,那做事就比较容易坚持了。

之后印象比较深的成功案例是硕士毕业论文。当时是截稿日前一天,我连写了31小时的论文,在截稿时间前40分钟提交了我的毕业论文。当时是拖延症遇到截止日期时的效率大爆发状态,所以情况有点不一样。不过仔细回忆一下,我记得当时写论文时头脑进入了一种麻木的状态。可能是熬夜太疲倦了,我平时每分钟会出现3次的各种分心的念头在当时完全没有出现。但这种麻木又不同于完全的大脑疲倦,因为我调用专业知识时完全不受阻碍,思维运转速度正常,只有在分心这方面的活跃程度大幅度下降了。这个可能是拖延遇到截止日期时的特殊反应,不适用于解决平日兴趣消失后的抵触状态。

学生生涯结束以后,我好像就再也没有成功的让自己进入某种规律的枯燥事务中去。不过等等,我其实并不觉得写程序是一件枯燥的事啊,这个抵抗情绪的原因应该不是枯燥这么简单。它似乎没有什么特别的理由,就是有一天,我突然变得很抵触做某件工作,总是很想逃避。
想解决这个问题,我需要一种压抑自己想逃避的心情的能力,或者说方法,某种思考工具。

对这个问题最常见的讨论就是"自控力"了。我也读过几本自控力方面的书,也看了《少有人走的路》,不过想让我开始行动,只是读几本书还是远远不够的。开始行动需要某种契机,要等到某件事激起了我的3分钟热血,然后赶紧趁着这三分钟热血做一个决定,最好是当场就执行了这个决定的一部分,然后一个行动才有可能随之开始。依赖性太强也好自控力太差也好,这就是现在的我。最好的药是最对症的药,而不是理论上最站得住脚的药,道理说再多也无益,要看疗效。

Unity学习-01

06.07.2015, 8 条评论, 未分类, by , 2,958 views.

目标太大,需要学习的基础知识太多,所以分而治之,开了很多不同的系列。

这次重学Unity是为了给Moba系列写客户端用的。

Unity在我的工作领域中也是非常有价值的技能。估计今后的手游开发就是Unity领军,没cocos2dx什么事了。好可惜最初猜错了方向,不过也没真正投入什么,不过是几个练手用的个人项目而已。

回顾一下开各种系列的因果关系,应该是:

 

想研究网络协议 (L2tp系列)

|- 先练习一下网络编程 (Http服务器系列也算是网络编程练习了,不过要用在工作里,所以不公开了)

    |- 先做个Moba网游服务器端的实现,练练手 (Moba系列)

        |- 需要有个客户端,用来调试和服务器端的通信 (Unity系列)

 

刚入社的时候有个Unity研修,其实也学了点。不过当时赶时间,就决定做个2D游戏,也只看了2D编程的部分。

这次的Moba是3D的,所以要重新学3D部分。

从头学一个大分类的话,比起网上零散的教程,我更倾向于看书,更有效率,进度更可控。

这次在亚马逊的kindle商店下了很多教程的试读,最后选了一本交怎么用外部导入的asset的书,里面还捎带手讲了一下怎么做游戏和怎么用Photon做Unity的服务器端!找到这么对口的书,也真是奇遇。

顺便一提,现在国内的亚马逊上的书还是很少有kindle版。日本是10本书里9本有kindle版的话,国内就是10本里只有1本有kindle的比例,甚至更低。

我真的是受地理位置限制,没法看纸质版,有些时候只好去淘宝找人做pdf电子版。但是新书一般没有pdf版,而Unity啊cocos2dx这种版本更新频繁且剧烈的工具,对教程的时效性要求很高。反正最后我买的那本书是日文版的。嘛,配那么多图的技术类书籍,中日英我都ok啦= =。

这次的兴趣点在服务器端,客户端作为调试服务器端的工具,凑活凑活就可以。不过我毕竟没有3D编程经验,这个凑活的难度还是未知,搞不好是隐藏boss呢。

 

// 下面写着写着,突然发现应该同时实现客户端和服务器端,因为逻辑都要以服务器端为主的。所以回来写个注释。应该双线去开发这个原型。

 

【客户端】 有限地图和可移动的英雄角色

『服务器端』 对应的数据管理

『服务器端』 收到角色移动命令后,向所有人发送移动消息

【客户端】 右键发送移动消息。接收到移动命令后移动(应该预测移动?)

【客户端】 小兵,可接收移动命令,强制移动命令(弥补预测错误),血量控制命令,生死控制命令

『服务器端』 小兵的逻辑,接收命令和广播命令

...

 

通信方面准备多向lol学习一下。这里先记录一个相关内容的博客,以后用到了再检索。

https://nelsonslog.wordpress.com/2014/08/07/league-of-legends-game-protocol/

最近搞了很多简易HTTP服务器端,参考了各种代码。

今天在参考nanohttpd写我自己的java版HTTP服务器时,发现nanohttpd的示例程序发出的response接收起来很慢。

研究了一下代码,貌似是因为nanohttpd最近刚刚merge了一个别人写的gzip格式输出的pull request,但没有好好检查,导致返回Content-Encoding是gzip的response时,既没有添加Content-Length,又没有使用chunked Transfer-Encoding,这再加上keep-alive,根本就是断了浏览器感知response长度的一切手段,难怪chrome收他的response这么慢,人家只能傻傻的等你服务器端超时关闭连接了啊。

添加一行代码,在gzip输出时启用chunked格式,响应时间立刻从5s降到37ms。我看这次改动简洁易懂,有实践证据,也有理论支撑,把握挺大的,就鼓起勇气发出了我个人账户的第一个pull request。

这次虽然是第一次用私人账户发pull request,但其实我们公司管理代码就是用github,我在公司里常常要发pull request,所以也没什么新鲜感了。

听说有拖延症的人怕自己完不成任务,所以尽量少接任务,结果完成效率还是不尽如人意。

结构化拖延理论认为,有拖延倾向就更应该多接任务,这样为了逃避任务A而去做任务B,不知不觉就能搞定大部分工作了。

所以我要挖新坑,哼哼。

最近在看很多通信协议的东西,也需要看Unix网络编程。但网络编程这东西,没有个具体的需求的话,我也不知道这么些函数,这些模型都适合什么场景。

为了给自己一个练手的空间,这次准备尝试一下对实时网络通信质量要求非常高的领域——MOBA类游戏。

以往做的游戏都是websocket就能搞定的小玩意儿,一点儿也感觉不到各种网络通信方式之间的性能差别。MOBA类游戏有一个最重要也最容易分辨的质量标准,就是延迟。UDP到底比TCP快多少?怎么能在保证快速响应和在有丢包风险的连接上保证逻辑正确呢?还是实践出真理吧。