月度归档:2013年01月

模拟argc和argv

昨天工作终于到一个需要使用glog但又不想繁琐的修改现有逻辑,苦思冥想最终通过模拟argc和argv来达到目的:

虽然看起来很蛋疼,但总算在年代久远的代码中能够正常使用了。

程序算法与人生选择(转)

每年一到要找工作的时候,我就能收到很多人给我发来的邮件,总是问我怎么选择他们的offer,去腾讯还是去豆瓣,去外企还是去国内的企业,去创业还是去考研,来北京还是回老家,该不该去创新工场?该不该去thoughtworks?……等等,等等。今年从7月份到现在,我收到并回复了60多封这样的邮件。我更多帮他们整理思路,帮他们明白自己最想要的是什么。(注:我以后不再回复类似的邮件了)。

我深深地发现,对于我国这样从小被父母和老师安排各种事情长大的人,当有一天,父母和老师都跟不上的时候,我们几乎完全不知道怎么去做选择。而我最近也离开了亚马逊,换了一个工作。又正值年底,就像去年的那篇《三个故事和三个问题》一样,让我想到写一篇这样的文章。

几个例子

当我们在面对各种对选择的影响因子的时候,如:城市,公司规模,公司性质,薪水,项目,户口,技术,方向,眼界…… 你总会发现,你会在几个公司中纠结一些东西,举几个例子:

  • 某网友和我说,他们去上海腾讯,因为腾讯的规模很大,但却发现薪水待遇没有豆瓣高(低的还不是一点),如果以后要换工作的话,起薪点直接关系到了以后的高工资。我说那就去豆瓣吧,他说豆瓣在北京,污染那么严重,又没有户口,生存环境不好。我说去腾讯吧,他说腾讯最近组织调整,不稳定。我说那就去豆瓣吧,慢公司,发展很稳当。他说,豆瓣的盈利不清楚,而且用Python,自己不喜欢。我说,那就去腾讯吧,……
  • 还有一网友和我说,他想回老家,因为老家的人脉关系比较好,能混得好。但又想留在大城市,因为大城市可以开眼界。
  • 另一网友和我说,他想进外企,练练英语,开开眼界,但是又怕在外企里当个螺丝钉,想法得不到实施。朋友拉他去创业,觉得创业挺好的,锻炼大,但是朋友做的那个不知道能不能做好。
  • 还有一网友在创新工场的某团队和考研之间抉择,不知道去创新工场行不行,觉得那个项目一般,但是感觉那个团队挺有激情的,另一方面觉得自己的学历还不够,读个研应该能找到更好的工作。
  • 还有一些朋友问题我应该学什么技术?不应该学什么技术?或是怎么学会学得最快,技术的路径应该是什么?有的说只做后端不做前端,有的说,只做算法研究,不做工程,等等,等等。因为他们觉得人生有限,术业有专攻。
  • 等等,等等……

我个人觉得,如果是非计算机科班出生的人不会做选择,不知道怎么走也罢了,但是我们计算机科班出生的人是学过算法的,懂算法的人应该是知道怎么做选择的

【排序算法】

你不可能要所有的东西,所以你只能要你最重要的东西,你要知道什么东西最重要,你就需要对你心内的那些欲望和抱负有清楚的认识,不然,你就会在纠结中度过。

所以,在选择中纠结的人有必要参考一下排序算法。

  • 首先,你最需要参考的就是“冒泡排序”——这种算法的思路就是每次冒泡出一个最大的数。所以,你有必要问问你自己,面对那些影响你选择的因子,如果你只能要一个的话,你会要哪个?而剩下的都可以放弃。于是,当你把最大的数,一个一个冒泡出来的时候,并用这个决策因子来过滤选项的时候,你就能比较容易地知道知道你应该选什么了。这个算法告诉我们,人的杂念越少,就越容易做出选择。
  • 好吧,可能你已茫然到了怎么比较两个决策因子的大小,比如:你分不清楚,工资>业务前景吗?业务前景>能力提升吗?所以你完全没有办法进行冒泡法。那你,你不妨参考一个“快速排序”的思路——这个算法告诉我们,我们一开始并不需要找到最大的数,我们只需要把你价值观中的某个标准拿出来,然后,把可以满足这个价值的放到右边,不能的放到左边去。比如,你的标准是:工资大于5000元&&业务前景长于3年的公司,你可以用这个标准来过滤你的选项。然后,你可以再调整这个标准再继续递归下去。这个算法告诉我们,我们的选择标准越清晰,我们就越容易做出选择

这是排序算法中最经典的两个算法了,面试必考。相信你已烂熟于心中了。所以,我觉得你把这个算法应用于你的人生选择也应该不是什么问题。关于在于,你是否知道自己想要的是什么?

排序算法的核心思想就是,让你帮助你认清自己最需要的是什么,认清自己最想要的是什么,然后根据这个去做选择

【贪婪算法】

所谓贪婪算法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择(注意:是当前状态下),从而希望导致结果是最好或最优的算法。贪婪算法最经典的一个例子就是哈夫曼编码

对于人类来说,一般人在行为处事的时候都会使用到贪婪算法,

  • 比如在找零钱的时候,如果要找补36元,我们一般会按这样的顺序找钱:20元,10元,5元,1元。
  • 或者我们在过十字路口的时候,要从到对角线的那个街区时,我们也会使用贪婪算法——哪边的绿灯先亮了我们就先过到那边去,然后再转身90度等红灯再过街。

这样的例子有很多。对于选择中,大多数人都会选用贪婪算法,因为这是一个比较简单的算法,未来太复杂了,只能走一步看一步,在当前的状况下做出最利于自己的判断和选择即可。

有的人会贪婪薪水,有的人会贪婪做的项目,有的人会贪婪业务,有的人会贪婪职位,有的人会贪婪自己的兴趣……这些都没什么问题。贪婪算法并没有错,虽然不是全局最优解,但其可以让你找到局部最优解或是次优解。其实,有次优解也不错了。贪婪算法基本上是一种急功近利的算法,但是并不代表这种算法不好,如果贪婪的是一种长远和持续,又未尝不可呢?

【动态规划】

但是我们知道,对于大部分的问题,贪婪法通常都不能找出最优解,因为他们一般没有测试所有可能的解。因为贪婪算法是一种短视的行为,只会跟据当前的形式做判断,也就是过早做决定,因而没法达到最佳解。

动态规划和贪婪算法的最大不同是,贪婪算法做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。

动态规划算法至少告诉我们两个事:

1)承前启后非常重要,当你准备去做遍历的时候,你的上次的经历不但能开启你以后的经历,而且还能为后面的经历所用。你的每一步都没有浪费。

2)是否可以回退也很重要。这意思是——如果你面前有两个选择,一个是A公司一个是B公司,如果今天你错失了B公司,那到你明天还能不能找回来?

比如说:你有两个offer,一个是Yahoo,一个是Baidu,上述的第一点会让我们思考,Yahoo和Baidu谁能给我们开启更大的平台?上述的第二点告诉我们,是进入Yahoo后如果没有选好,是否还能回退到Baidu公司?还是进入Baidu公司后能容易回退到Yahoo公司?

【Dijkstra最短路径】

最短路径是一个Greedy + DP的算法。相当经典。这个算法的大意如下:

1)在初始化的时候,所有的结点都和我是无穷大,默认是达不到的。

2)从离自己最近的结点开始贪婪。

3)走过去,看看又能到达什么样的结点,计算并更新到所有目标点的距离。

4)再贪婪与原点最短的结点,如此反复。

这个算法给我们带来了一些这样的启示:

  • 有朋友和我说过他想成为一个架构师,或是某技术领域的专家,并会踏踏实实的向这个目标前进,永不放弃。我还是鼓励了他,但我也告诉他了这个著名的算法,我说,这个算法告诉你,架构师或某领域的专家对你来说目前的距离是无穷大,他们放在心中,先看看你能够得着的东西。所谓踏实,并不是踏踏实实追求你的目标,而是踏踏实实把你够得着看得见的就在身边的东西干好。我还记得我刚参加工作,从老家出来的时候,从来没有想过要成为一个技术牛人,也从来没有想过我的博客会那么的有影响力,在做自己力所能及,看得见摸得着的事情,我就看见什么技术就学什么,学着学着就知道怎么学更轻松,怎么学更扎实,这也许就是我的最短路径。
  • 有很多朋友问我要不要学C++,或是问我学Python还是学Ruby,是不是不用学前端,等等。这些朋友告诉我,他们不可能学习多个语言,学了不用也就忘了,而且术业有专攻。这并没有什么不对的,只是我个人觉得,学习一个东西没有必要只有两种状态,一种是不学,另一种是精通。了解一个技术其实花不了多少时间,我学C++的目的其实是为了更懂Java,学TCP/IP协议其实是为了更懂Socket编程,很多东西都是连通和相辅相成的,学好了C/C++/Unix/TCP等这些基础技术后,我发现到达别的技术路径一下缩短了(这就是为什么我用两天时间就可以了解Go语言的原因)。这就好像这个算法一样,算法效率不高,也许达到你的目标,你在一开始花了很长时间,遍历了很多地方,但是,这也许这就是你的最短路径

【算法就是Trade-Off】

你根本没有办法能得到所有你想得到的东西,任何的选择都意味着放弃——当你要去获得一个东西的时候,你总是需要放弃一些东西人生本来就是一个跷跷板,一头上,另一头必然下。这和我们做软件设计或算法设计一样,用时间换空间,用空间换时间,还有CAP理论,总是有很多的Trade-Off,正如这个短语的原意一样——你总是要用某种东西去交易某种东西

我们都在用某种东西在交易我们的未来,有的人用自己的努力,有的人用自己的思考,有的人用自己的年轻,有的人用自己的自由,有的人用自己的价值观,有的人用自己的道德…… …… 有的人在交换金钱,有的人在交换眼界,有的人在交换经历,有的人在交换地位,有的人在交换能力,有的人在交换自由,有的人在交换兴趣,有的人在交换虚荣心,在交换安逸享乐…… ……

每个人有每个人的算法,每个算法都有每个算法的purpose,就算大家在用同样的算法,但是每个人算法中的那些变量、开关和条件都不一样,得到的结果也不一样。我们就是生活在Matrix里的一段程序,我们每个人的算法决定着我们每个人的选择,我们的选择决定了我们的人生

==转自陈皓博客 酷壳 – CoolShell.cn ,请勿用于任何商业用途==

开发中的实例-进程-线程比较

我们都知道当今主流处理器都是多核心,因此在 linux后台程序开发中都需要开启多个调度单元来充分利用cpu资源。进程是资源分配的最小单位,线程是处理器调度的最小单位。为了达到这一目的结合这一基本规律,可以衍生出几种常见的程序结构:单实例单进程多线程,单实例多进程单线程,多实例单进程单线程(多进程多线程的编码复杂度和出错概率高使得生产环境中使用得很少,单实例即一个可执行程序)。

编码复杂度

部署难易度

单实例单进程多线程

较简单

容易

单实例多进程单线程

较复杂

容易

多实例单进程单线程

简单

较容易

1.单线程/单进程与多线程/多进程的优劣

a)单线程/单进程最大的毛病就是无法充分利用处理器资源,而这正是多线程/多进程的强项。
b)多线程/多进程的编码复杂度比单线程/单进程的程序高了一大截。

2. 多进程和多线程的优劣

a)多进程程序需要处理fork出的两个分支,每多加一个进程你的工作量都会直线上升;多线程实际上只需要编写一个接口,让线程去执行就好,编码上相对容易。
b)多进程拥有OS天生的隔离性,而多线程存在资源耦合,需要小心处理共享资源,而无状态性在server开发中至关重要,因此这里多线程程序会多一点工作量。
c)相同的是多进程和多线程都能很好的利用多核心处理器资源。

[总结]

1.单进程单线程模型对开发人员十分友好,只要保证了程序的无状态独立性,那么就很容易通过多实例去扩展它。
2.多进程/多线程的程序对开发人员有更高的技能要求,对部署和运营更加友好。

我的助理辞职了!—— 写给频繁跳槽的你(转)

也许我们就像偏向选择喜欢的、爱好的、兴趣等作为工作激情源泉的人群之一,无论如何我们都惯以为后退找一百个理由,而不愿意去面对只有一个理由的“前进”。与此同时,这些喜欢的、爱好的、兴趣的,只会被这岁月流年之间被消磨的一干二净。还是要决定奋斗 Or 止步不前吗?

每当我明白到有些道理是必须自我领悟,才能让人深刻体会的时候。茫然之间才发觉这个过程居然整整花了我四年的时间。但无论如何,过程与结果终归是两个相辅相成的产物,也许我们没有办法掌控你我所处于的环境变化。至少你应该要为掌控自己的生活而努力或奋斗过。

—— “时间它只负责流动,不负责与你成长”

原文:

当时公司招了大批应届本科和研究生毕业的新新人类。平均年龄25岁。那个新的助理,是经过多次面试后,我亲自招回来的一个女孩。名牌大学本科毕业,聪明,性格活泼。私下里我得承认,我招她的一个很重要的原因,除了她在大学里优秀的表现之外,还因为她写了一手漂亮的字。女孩能写一手好字的不多,尤其像她,看起来长发飘飘,多么女性化的一个姑娘,一手字却写的铿锵倜傥,让我对她不由多了很多好感。

手把手的教。从工作流程到待人接物。她也学的快。很多工作一教就上手。一上手就熟练。跟各位同事也相处的颇融洽。我开始慢慢的给她一些协调的工作,各部门之间以及各分公司之间的业务联系和沟通让她尝试着去处理。

开始经常出错。她很紧张,来找我谈。我告诉她:错了没关系,你且放心按照你的想法去做。遇到问题了,来问我,我会告诉你该怎么办。仍然错。又来找我,这次谈的比较深入,她的困惑是,为什么总是让她做这些琐碎的事情?我当时问她:什么叫做不琐碎的工作呢?

她答不上来,想了半天,跟我说:我总觉得,我的能力不仅仅能做这些,我还能做一些更加重要的事情。那次谈话,进行了1小时。我知道,我说的话,她没听进去多少。后来我说,先把手头的工作做好,先避免常识性错误的发生。然后循序渐进罢。

半年以后,她来工作室找我,第一次提出辞职。我推掉了约会,跟她谈辞职的问题。问起辞职的原因,她跟我直言:本科四年,功课优秀,没想到毕业后找到了工作,却每天处理的都是些琐碎的事情。没有成就感。我又问她:你觉得,在你现在所有的工作中,最没有意义的最浪费你的时间精力的工作,是什么?她马上答我:帮您贴发票,然后报销,然后到财务去走流程,然后把现金拿回来给您。

我笑着问她:你帮我贴发票报销有半年了吧?通过这件事儿,你总结出了一些什么信息?

她呆了半天,答我:贴发票就是贴发票,只要财务上不出错,不就行了呗,能有什么信息?

我说,我来跟你讲讲,当年我的做法吧:98年的时候,我从财务被调到了总经理办公室,担任总经理助理的工作。其中有一项工作,就是跟你现在做的一样,帮总经理报销他所有的票据。本来这个工作就像你你刚才说的,把票据贴好,然后完成财务上的流程,就可以了。

其实票据是一种数据记录,它记录了和总经理乃至整个公司营运有关的费用情况。看起来没有意义的一堆数据,其实它们涉及到了公司各方面的经营和运作。于是我建立了一个表格,将所有总经理在我这里报销的数据按照时间,数额,消费场所,联系人,电话等等记录下来。

我起初建立这个表格的目的很简单,我是想在财务上有据可循,同时万一我的上司有情况来询问我的时候,我会有准确的数据告诉他。通过这样的一份数据统计,渐渐的我发现了一些上级在商务活动中的规律,比如,哪一类的商务活动,经常在什么样的场合,费用预算大概是多少;总经理的公共关系常规和非常规的处理方式。等等等等。

当我的上级发现,他布置工作给我的时候,我会处理的很妥贴。有一些信息是他根本没有告诉我的,我也能及时准确的处理。他问我为什么,我告诉了他我的工作方法和信息来源。

渐渐的,他基于这种良性积累,越来越多的交待更加重要的工作。再渐渐的,一种信任和默契就此产生,我升职的时候,他说我是他用过的最好用的助理。

说完这些长篇大论,我看着这个姑娘,她愣愣的看着我。我跟她直言:我觉得你最大的问题,是你没有用心。在看似简单不动脑子就能完成的工作里,你没有把你的心沉下去,所以,半年了,你觉得自己没有进步。她不出声。但是收回了辞职报告。

又坚持了3个月,她还是辞职了。这次我没有留她。让她走了。

后来她经常在MSN上跟我聊天。告诉我她的新工作的情况。一年内,她换了三份工作。每一次都坚持不了多久。每一次她都说新的工作不是她想要的工作。05年的时候,她又一次辞职了。很苦恼,跑来找我,要跟我吃饭。我请她去写字楼后面的商场吃日本料理。吃到中途,忽然跟我说:我有些明白你以前说的话是什么意思了。

所谓的职业生涯,其实你很难预测到你将来真正要从事什么工作,将来所要从事的工作,是否跟你在大学里学的专业有关。大多数人,很有可能将来所作的工作,跟他当初所学的专业一点关系都没有。从22岁大学毕业在26岁之间这四年,重要的不是你做了什么,重要的是你在工作中养成了怎么样的良好的工作习惯。这个良好的工作习惯,指的是:认真,踏实的工作作风,以及是否学会了如何用最快的时间接受新的事物,发现新事物的内在规律,比别人更短时间内掌握这些规律并且处理好它们。具备了以上的要素,你就成长为一个被人信任的工作的人。

人都有惰性,也都愿意用那些用起来顺手的人。当你具备了被人信任的基础,并且在日常的工作中逐渐表现出你的踏实,聪明,和细致的时候,越来越多的工作机会就会提供到你面前。原因很简单,用一句话就能交代清楚并且能被你顺利完成的工作,谁愿意说三句话甚至半小时交待一个怎么都不明白的人呢?沟通也是一种成本,沟通的时间越少,内耗越少,这是作为管理者最清楚的一件事。

当你有比别人更多的工作机会去接触那些你没有接触过的工作的时候,你就有了比别人多的学习机会,人人都喜欢聪明勤奋的学生,作为管理者,大概更是如此。

一个新手,大多数新手,在这四年里,是看不出太大的差距的。但是这四年的经历,为以后的职业生涯的发展奠定的基础,是至关重要的。很多人不在乎年轻时走弯路,很多人觉得日常的工作人人都能做好没什么了不起。然而就是这些简单的工作,循序渐进的、隐约的,成为今后发展的分水岭。

漫不经心的对待基层工作的最大的损失,就是将看似简单的事物性处理方式,分界成为长远发展的能力问题。

聪明的人,总是不认为自己的能力有问题。时间长了,他会抱怨自己运气不好,抱怨那些看起来资质普通的人,总能比自己更能走狗屎运。抱怨她容貌比自己好,或者他更会讨领导欢心。等等等等。慢慢的,影响心态。所谓的怀才不遇,有时是这种情况。

工作需要一个聪明人,工作其实更需要一个踏实的人。在聪明和踏实之间,我更愿意选择后者。

而踏实,是人人都能做到的。和先天条件没有太大关系。

总结下常见插件机制

插件机制: 框架 + 扩展接口 + 模块/插件

框架提供基本功能暴露扩展接口,用户基于扩展接口编写模块/插件。应用场景通常是框架维护核心逻辑,扩展处理业务逻辑,因为核心变动小且慢,业务变更多且快。

【分类】

  1. 基于动态库的插件机制
    dll或则so,OS天生的隔离性使得业务和框架能够分离,方便扩展,apache等都是用这种方式。
  2. 基于解释型语言的插件机制
    wireshark的lua插件机制等。
  3. 自定义解析框架的插件机制
    chrome浏览器的插件机制,js+html文件包,这种方式有时候会与类型2相似,但是至少做了一些自我封装和修改。

【优劣】

  1. 基于动态库的传统插件机制: 思想成熟,开发简单,性能高 需要编译且调试复杂。
  2. 基于脚本引擎的插件机制: 开发方便,扩展性好,无需编译 性能可能要受脚本解析器的影响。
  3. 基于自定义解析框架的插件机制 应用场景广泛,扩展性好,通常无需编译 框架解析框架开发可能较为复杂,性能取决于框架。

【总结】

  1. 对于后台服务器开发这种对性能究极需求的场景,通常采用动态库的机制。
  2. 对于游戏或者工具类对扩展性要求更高,性能不是第一目标的场景下,解释型脚本引擎将更有生命力。
  3. 对希望规范和统一插件方式,或者自身存在某些隐形要求的场景,通常会自定义解析引擎。