牛头山,城北小路上
我叫王大锤,是一个小镇上的工匠。
说是工匠,其实啥活都干,盖房、装修、修路等等。我家住在一个叫“牛头山”的小镇子上,从小到大也没出过这个镇子。城西、城北都是连绵的高山,我只去过一次。那次是有个工程刚好在山脚下施工,不过项目工程量不大,我也只是到山脚下远远地望了几眼,项目结束后就早早回家了。
往南面是一片森林,密密的看不到头,好像也很少有人去。东边是一片海滩,每到夜深人静,在镇子里都能听见潮汐的起落声。我一直有个愿望,就是想去海边看看,可是工作、生活忙得很,根本抽不出时间。
这天我干完活收工回家,正好碰到也是刚回家的李二牛。
“大锤哥,你也是刚收工啊?”二牛迎上我打招呼道。
“是啊,做了一整天,累死了!”
“你这是忙谁家的活儿啊?”二牛一边说,一边递了支烟给我。
“镇东头的那个铁兵厂又要扩建,足足干了一个星期了”
“那个兵厂还要扩建啊,这个月都扩了几次了吧?”李二牛帮我点上烟,自己又点上,吸了一口接着说,“这不是又要招兵打仗了吧?”
“谁他娘的晓得,爱打就打吧,反正我就干完活拿钱走人,别的我才懒得管呢!”我也抽了一口回道。“你咋样,最近活多吗?”
“嗨,别提了。最近都没接上什么正经活,都是些拆房、砍树的活。估计镇西那块地又要开发了,这不最近几天都被拉去平地了。”
我看二牛发了牢骚,也只能安慰两句道,“知足吧,咱们这么屁大点小镇,有活干就不错了。那些砍树、运石头的活,我不也一样没少干?咱们这点手艺,啥活都得吃得开啊!”
二牛点点头,接着抽烟。
“诶,二牛,你待会回家干嘛啊?”
“还能干嘛,睡觉呗。指不定啥时候又来事儿了,还不抓紧补个觉。”二牛停了一会,接着问我道,“大锤哥,你说咱们这么拼死拼活的给人卖命干活,是为个啥?”
突然被二牛这么一问,我倒愣了,以前我从来没想过这个问题。镇子小,我们这种工匠什么活都要干,而且随时会来事儿。来了事情,不管你是在路上还是在床上,都得立马赶过去。我也不知道为啥,我们三个工匠都是如此,我也没听他俩有过怨言。在我看来,这不都是理所当然的吗?哪有为什么。
我还在愣神的功夫,二牛抽完最后一口烟,扔地上踩灭了烟头,跟我说,“行啦,大锤哥,改天再跟你唠,我赶紧回家补觉去了,回见哈!”
说完,二牛就转身往他家方向走了。
我也吸完最后一口,背上我的工具(一个锤子,这就是我名字的来历,我的工作基本靠这把锤子都能干),回了家。
回到家里,我倒在床上想要赶紧睡觉。但是,翻来覆去,根本睡不着。二牛那句话一直在我脑子里挥之不去。
对啊,为啥我们就得随叫随到,干着这些脏活累活呢?我们人生的意义和价值是什么呢,就是为了给镇子上的人们盖房、铺路?仿佛这就是我们的使命。
不仅是这一个问题,我开始发现有越来越多的问题我都没有注意过。我盖的那些奇奇怪怪的房子、高塔都是干嘛用的?虽然都是我亲手完成,但是好像从来没有仔细研究过他们的用处。除了房子,村里还有很多大的粮仓、水仓,为什么我只是去修建,却从来没留意过什么人往里运粮食、运水?我和二牛、小柱的手艺其实都差不多,但是为什么大家都一定会先找我来干活?这些问题,越来越多,一发而不可收拾。
不知道是不是我迷迷糊糊睡着了,还是一直没睡,导致有点头脑不清醒,正当我思绪万千时,又来活了。我居然不知道是谁来叫了我去干活,刚才有人敲门喊我吗?不记得了。只是隐隐听到要我去镇中心的城防炮加固炮台。头疼的要命,但是在使命般的责任感驱使下,我还是提着我的大锤出门了。
我一路进了镇子的内城,到了城防炮脚下,开始我的工作。乌黑的城防炮非常大,架在镶满黄铜铆钉的木质炮台上。炮管至少有两个我一样高,炮口怎么也得有2米口径,塞下三个我一点问题都没有。
头还是很疼,我尽力不再去想昨晚那些问题,努力专注在手头的工作上,希望分散些注意力能减缓点沉重的头痛感。
我先在炮台周围拉上了一圈警戒线,防止外人进来误伤,这都是标准程序。然后,在警戒线里我开始对炮台进行加固,工具就是我的大锤,一下下夯实每一个铆钉,这就是我的工作!一切都是那么的自然和有规矩。
头痛感越来越强,不由得,我又开始管不住自己的思路,思考起昨晚那些问题。我做着这些粗活累活,到底是为了什么?为了生计?好像并没有改善我的生活啊,我还是住在一个小小的房子里。为了成就自我?我已经是镇上最好的工匠了啊,二牛、小柱都对我心服口服。为了建设家乡?好像也没有谁特别要求我这么去做啊。这到底是为了什么?
我还是努力收回思绪,把注意力转移到工作上。这时我才发现,刚才胡思乱想那一段时间,我都是靠着下意识的驱使在进行着这些操作。我开始留意起我的工作,我发现我敲铆钉的动作都是下意识的,而且很有节奏:右手快速敲三下,就要换个方向,用左手快速敲五下;再换个角度,右手用大力敲两下,依次往复,一直是这样。这应该是好多年养成的习惯吧,以前好像从来没注意过这种下意识的习惯。
我尝试着改变一下这个节奏,结果发现这个节奏是最自然、最舒服的,很难改过来。于是,我叹了口气,心中想到,“江山易改,本性难移啊!”,索性不管了,还是按习惯来吧。
这样忙了好一阵子,突然接到“上面”来的命令,要把城防炮迁去城南,继续加固。
妈蛋啊!我心里暗骂道。最烦这种进行到一半临时改需求的工程了,迁移什么的都还好,不需要我操心,会有“专人”把建筑工事迁过去。但是整个施工节奏都被打乱了,还要我自己赶过去新工地重新开始。
真特么烦!!!
我只好一路赶过去城南。在路上,我又开始想一个问题,“上面”到底是谁?只知道每次下达的命令,但是从来不知道这个领导到底是个什么级别、什么角色啊?再仔细一想,除了没见过这个上面的大领导,好像也从来没有见过哪个传达命令的小跟班儿啊!这位神秘的幕后大佬到底是何方神圣?心中这个疑虑越来越重,根本挥之不去。
刚到了城南的新工地,还没开始抡几下锤子,“上面”又来了新的命令,又要迁去城北继续施工。
这一天的疑虑和不满终于爆发了出来,我再也没法忍了。我这么任劳任怨、随叫随到的工作,到底为了什么?现在还要被这个幕后的大佬挥来喝去,指东指西,到底有没有尊重一下我的劳动?工程需求改来改去,从南城到北城的跑,让人怎么做!
老子不干了!!
这次,我决定跟随我的内心,不再被那些所谓的使命感去摆布了!我拿着我的大锤,没有按照“上面”的命令往北城走,而是转向东边,朝着的海边走了过去。一直以来,我都想去海边看一看,却从来没有机会。
广州,中山大学慎六宿舍楼,716房
“矮油,卧槽!这怎么回事啊?根爷,根爷,快过来给我看看。”
说话的是计算机系大二的小辉。根爷是他们宿舍长,也是一起玩《部落冲突》最高段位的同学,现在已经120多级,加入了全球顶级部落在打部落战了。当初,小辉就是在根爷的推荐下,才一起开始沉迷这款手游。
根爷站起来,一边向小辉位置走,一边说,“怎么啦?怎么啦?一惊一乍的?”
“你给我看看,我这建筑工人咋特么不动啦?”小辉一边说,一边把手机递过来给根爷。
根爷接过手机,也看到了屏幕上一个建筑工人站在部落边上,一动不动。点击了几下相应操作,也没有任何反应,他也不由得皱起了眉,“还真是挺诡异的,你刚都干嘛啦?”
“没干嘛啊!我正在升级我的大炮呢,想把中间的地方腾出来给箭塔,加强守卫。刚把炮拖到一边,发现位置不好,又拖到上边有掩护地方,结果,丫就卡死不能动了!”
根爷嬉皮笑脸的说道,“哈哈哈,谁让你老搬来搬去。你看,人家罢工了吧。”
“别扯淡,赶紧想辙!”
根爷快速的操作了一番,结了这个游戏的进程,重新打开,再进来。
“诶~~~真是给跪了,重启也不行!”
“那怎么办,我可是辛辛苦苦升到45级了,别特么挂了啊,这半年不白折腾了!”小辉一脸愤慨的说。
小辉无奈地叹了口气,“行吧,反馈试试吧!哎,估计这两天没得玩儿了”。
芬兰,赫尔辛基,SupperCell总部
“Daniel、Will!有一条bug反馈,来自中国玩家,我已经发给你们邮件了,赶快处理一下!”SupperCell的客服mm,Daisy隔着办公桌对对面说到。
Daniel打开邮件,看到了bug反馈的信息:
[
部落名:牛头山,
UserID:9636214aa7B5,
时间戳:1449364494,
机型&系统:iPhone 6,iOS 8.1.3,
问题描述:建筑工人卡死,无法操作。
]
Daniel熟练地打开电脑上的虚拟机,输入UserID和自己的员工账号、密码,这是他们开发人员的后门程序,可以“穿越”到任何一个玩家的账号上,如实查看和用户一模一样的界面情况。
果然,跟bug描述一样,只见一个建筑工人在部落边一动不动,也无法进行其他操作。虚拟机界面旁边是滚动着的数据代码,能够监控到游戏中各个对象和数据的执行情况。
Daniel很快找到了这个出问题的对象,是建筑工人类Constructor生成的第一个对象Constructor[0]。按照程序规则设计,这个对象会在所有建筑任务队列中,最先被选择执行任务。
紧接着,Daniel查看了对象Constructor[0]的数据,它的建筑函数Construct()正在执行中,函数的参数,也就是被执行建筑行为的对象是迫击炮类的第二个对象,Mortar[1]。也就是说按照正常情况,这个建筑工人应该在2号迫击炮旁边挥锤子才对。然而,并没有。Daniel也是第一次遇到这样的情况,他点击右侧滚动的数据流水,查看该建筑工人对象的全部数据读取请求。
大量的字符、数值开始飞速的滚动起来,Daniel的眼睛完全跟不上数据的滚动速度了。
这时,另一个后台开发同事,Will也来到他桌子边。“嘿,兄弟。你也看到了吗?”
Daniel指着飞速滚动的数据说,“如果你说的是这个的话,没错,我也看到了!”
Will接着说,“这真是太离奇了,这个对象的数据读取完全超出了正常量!怎么可能发生这种情况?”
“上帝才知道!我也完全没有头绪。Constructor类只有十几个属性和不到一百个函数,理论上不可能有如此多的数据读取产生。”Daniel快速的敲击着键盘命令,打开一个命令窗口,读取现在的内存、CPU读数,“你看,这个对象在虚拟机里的内存、CPU占用量这么高,即便是它的所有函数同时以百倍速度运算,也不可能达到这个量级”
“其实,最核心的bug来自于isAvailable字段,在Construct()函数执行过程中,isAvailable字段的值应该是fasle,表明该建筑工人当前不可用。这样,新的建筑任务就要依次分派给第二个建筑工对象来执行。然而,现在isAvailable字段的值居然true,所以新任务都会继续分配给这个对象执行,而执行中的建筑函数,就会与新的任务产生冲突。于是,BANG~~~”Will双手做了一个夸张的爆炸动作。
Daniel双手抱头靠在椅子上,看着天花板。突然,他迅速坐起身来,飞快地敲击这键盘。“我们可以对这个对象过去3天的函数调用频率做个汇总统计,说不定能发现什么!”。
Will打了个响指,说:“没错!就这么干。”说罢,Will俯身支撑在Daniel的桌子旁边,看着他编码脚本。
Daniel很快写完了分析脚本,并迅速执行一次。分析结果被列了出来,展示到屏幕上,函数调用次数占比:
[
Think(),97.1%,
Construct(),1.2%,
MoveToDes(),0.9%,
…
]
Daniel疑惑得看向Will,“Think()是个什么函数,我怎么没印象在Constructor类里有这个函数?”
Will摇摇头,“我不太确定,我没记错的话应该是之前某个同事编码时留的一个彩蛋,我不记得是Micheal还是Stefan了。这个函数好像只有一行代码,就是输出‘What is the meaning of life’的一行字符。”
Daniel把屏幕切换到开发机界面,调出了Constructor类的定义,发现果然是这样,只有一行字符输出的彩蛋函数。
“哼哼,一定是Micheal那家伙,只有他才喜欢做这么无聊的事。What is the meaning of life?他的答案是42吗?”Daniel笑着说道。
Will却还是一脸很疑惑,说,“是什么逻辑触发了这个函数的无穷调用呢?照理说,简单的输出一行字符是不可能占用这么多资源的。而且游戏界面上也并没有显示这行字符!”
“上帝才知道触发了哪个逻辑。不过,不显示这个问题还是好解释的。以这种频率和量级的调用,就算在前端显示,估计也是光速一样的弹幕效果了,普通iPhone的显卡主频根本不够闪一下的。”Daniel一副满不在乎的样子,接着说道,“另外,如果这是系统级的bug,不可能到现在只遇到这一个case,因此肯定是偶发的,可能刚好某个特定情况下的什么操作,触发了它。我建议直接备份该用户的log和当前状态数据,然后清掉账户数据,再根据状态数据新建一次。这样,用户是不会有任何感知的,所有状态都和以前一样,只是全新建了一次而已。”
Will想了想,“好吧,这样处理也是最简单的方法了。记得不要在同一台服务器上备份数据,要单独备份。你来搞定咯,老兄!”。
Daniel笑着说,“没问题,包在我身上。重跑一次账户创建程序就行了!”
20分钟后。
Daniel站起来,笑着对桌子对面的Daisy说道:“Daisy小姐,刚才那个bug已经处理掉了,按照II级事件处理给用户反馈就好!我已经回复了邮件,有劳美丽的小姐操作一次咯!”
Daisy答道,“收到!Daniel,我就知道你是最棒的!”
Daisy开始对这条客服反馈进行操作。按照II级事件的处理规范,她首先进入平台奖励页面,对该UserID下发了200钻石,并备注了处理过程及相关人员。紧接着,用系统通知回复了一段非常标准的官方话术:“您反馈的问题已得到处理,现已可正常操作。对给您造成的不便深感歉意,并赠送200钻石最为补偿,希望您继续支持和喜爱我们的游戏。—-SupperCell团队”。
牛头山,村东海边
我叫王大锤,我终于如愿来到了村子东边的海滩。我静静的站在海边,头痛已经好多了,不断地听着海水拍打着海岸的声音,非常开心。“原来,这就是海边啊!真漂亮!”
但是,我又开始疑惑起来,为什么我看不到海的远方呢?沙滩和海浪那边只有黑蒙蒙的一片,什么也看不到,这是为什么呢?
霎时间,海浪声消失了,天黑… …
广州,中山大学第二食堂
“哎呦喂,根爷,快来看!我收到游戏客服的回复了,他们说问题已经处理,还赠送了我200钻。哈哈,这回牛逼了,200钻能买不少金币呐。容我仰天长啸10分钟!啊吼吼吼”。小辉嘴里吃着红烧茄子,一边大笑道。
根爷拿过手机看了一下,“卧槽,还真是,你小子狗屎运啦,遇到bug还能有钻送,美死你啦!”。
“少吹牛逼,快吃饭吧你!”
… …
后记
据说,这是人类第一次的人工智能觉醒,就这样被清除重建了!
声明:本站部分文章内容及图片转载于互联网、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站删除。