用命令行编译Objective-C程序
此文来自本人原JavaEye博客,原文地址。
最近在看Objc的开发,虽然Xcode很好用,但是还是不太习惯这种大型的IDE开发。 于是自己尝试着在Terminal下面编译。 先是最简单的一段程序。
#import <Foundation/Foundation.h>
int main(int argc, const char *argv[])
{
NSLog(@"Hello, World!");
return 0;
}
直接 gcc helloworld.m,报错。
错误提示如下
Undefined symbols:
"___CFConstantStringClassReference", referenced from:
cfstring=Hello, World! in ccCxrkF8.o
"_NSLog", referenced from:
_main in ccCxrkF8.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
猜测可能lib的位置不对,于是find了一下“Foundation”这个framework的位置,用以下命令编译:
gcc helloworld.m -L/System/Library/Frameworks/Foundation.framework/
还是一样的错误。
无奈之下man gcc从头看到尾。又去google了一下gcc for macosx。发现有一个-framework的选项。尝试了一下。
gcc helloworld.m -framework Foundation
终于成功了
2010-04-22 19:11:11.643 a.out[8932:903] Hello, World!
总结一下:macosx下面,objc的系统调用都是集成在framework里面的,要想编译的话,就必须用-framework选项将framework包含进来才行。
MacOSX中链接boost库
此文来自本人原JavaEye博客,原文地址。
今天在编译一个用到boost_program_options的库的时候出现了一点点小问题。总是提示说找不到boost_program_options这个库。
去/usr/local/lib下面看了一下,发现原来改名成libboost_program_options-mt.dylib了。搜了一下名字中这个mt的意思。
原来是boost1.33的新特性,就是区分了某些lib是单线程或者多线程的。这个区分导致必须显式的指明使用的是多线程还是单线程的库。
自然mt就是指的多线程,st指的单线程。
改用-lboost_program_options-mt以后,编译ok。问题解决。
如何使用logger将错误信息输出到日志
此文来自本人原JavaEye博客,原文地址
今天在做分析http错误请求处理的时候遇到一个问题:当发生500错误的时候,如何将错误输出到日志当中呢?
搜了一下python的doc,在logging模块中有不起眼的一行代码提供了解决方案。
mylog.error('error!', exc_info=True)
其中,mylog就是Logger实例,当exc_info设置为True的时候,logger就会自动的调用sys.exc_info()函数,将traceback的信息打印到日志中。
求职总结
此文来自本人原JavaEye博客,发表于2009年10月26日。原文地址
好吧, 求职总算告一段落了.
从13号参加第一场笔试, 到24号拿到网易游戏offer, 20天时间的经历, 算是人生一大笔财富了.以后可能就没有这样的机会去体验那种心情了.
写一点总结, 希望能够帮助仍然在水深火热之中的同学和朋友.
一. 职业规划
求职的头等大事, 就是树立一个详细完整有可行性的职业规划.
其实职业规划, 不能是等到求职的时候才去想, 它的作用应该是指导大学4年期间学习方向, 以及指导工作以后的研究方向, 甚至可以决定一生的奋斗方向.所以, 最好在进大学1-2年内就确定自己的职业规划, 为之去努力, 然后在求职的时候, 针对你想进入的公司简单修改.不过这就属于是求职技巧的内容了.
职业规划我个人认为应该包含以下几个部分.1.我想要从事什么行业. 2.我想进这个行业内的哪些公司. 3.我进这些公司以后想要从事什么岗位. 4.我进公司以后应该怎么奋斗. 以上几个部分, 必须有足够能说服自己的理由.说服自己是关键, 别人的意见可以作为参考, 但是一定要有自己的观点.
- 就拿我自己来说吧, 我想从事互联网行业, 因为互联网行业是中国目前发展最快的行业之一, 可能甚至没有之一.
- 我想进的公司有, Google:互联网老大, 不用多说;网易游戏:中国自主研发实力最强的游戏公司, 而游戏行业是互联网行业中产值最大的部分;百度, 阿里巴巴, 腾讯:中国互联网三强, 产值过千亿的公司.
- 我想要从事的岗位是基于Unix或者linux平台的服务器端网络程序开发.因为自己是Open Source的狂热爱好者, 而且类Unix平台的服务器的市场占有率相当高.网络, 是未来的发展方向, 我们的生活必将和网络紧密结合, 以后, 上网这个词一定会消失或者变成纪念, 因为我们无时无刻不在上网.
- 进入公司以后, 我希望在4-5年内做到部门leader, 哈哈!
提过了愿景, 实现情况就是, 我已经满足了前三点, 第四点, 我一定会努力去实现它的.
关于想进的公司, 其实google还是心中永远的向往, 可惜google不招人啊…囧..剩下4个, 网易游戏和阿里巴巴的offer到手, 百度和腾讯被鄙视..恩.可能是骂百度太多败了不少人品吧..呵呵..
在面试中, 总会被不停的问到有关职业规划相关的问题.这个时候, 一个清晰明确的规划就十分重要了.当然, 要针对每个公司修改, 不能把面试google的回答去回答百度的问题, 那样不被刷才怪.
二. 简历
简历有两种, 一种是在网上招聘系统填写的在线简历, 另一种是自己精心制作的, 面试时候面试官会盯着问的简历.
网上申请时在招聘系统内填写的简历, 其实个人感觉不是很重要, 主要是系统用来刷一帮笔试名单用的. 面试官不会看.而且, 就算这一关被刷了, 也可以去霸王笔么.
真正重要的, 是自己精心制作的简历. 简历最好大概2-3页大小, 包括个人信息, 获得奖项, 项目经验等等. 对于偏技术类的岗位, 我认为, 项目经验是最重要的, 因为面试官会不厌其烦的问你项目相关的事项, 而且几乎全部的面试官, 都喜欢问你最不熟悉的那个项目.
关于写什么项目, 其实非常重要. 因为2-3页纸有限, 对于项目多的同学来说, 可能根本不够. 取舍就显得很重要了. 尽量把重要的, 与你所应聘的职位相关的项目写上去, 当然, 写上去的项目, 你的内心必须对这个项目无比熟悉. 因为这个项目就是一个大大的陷阱, 是我们设下的陷阱, 让面试官跟着我们的思路问问题的陷阱. 如果陷阱把老虎引过来了, 自己却没有办法制服老虎, 那么被老虎吃了就是唯一的下场. 当然, 风险大收益也大, 如果这个问题答的好, 面试官那里的得分可是会大大增加的.
另一点关于简历项目的要点就是, 你的简历项目, 必须能够证明你能在一个团队内良好的与同事合作. 也就是说, 一个人参与的项目, 除非巨牛, 不然少写, 突出团队项目就要多写, 而且注意, 不是突出自己在团队中的重要性, 而是作为一整个团队所获得的成绩的项目.
其他关于简历的注意事项, 不一定一个公司一个简历, 如果你把自己所有的精华都写在一个简历里面, 那么拿着这个简历就可以了. 当然, 简历里面不能有错别字啊.
三. 笔试
其实我个人还是比较恐惧笔试的, 因为我不知道笔试要考什么内容, 而面试我大致清楚面试官会问什么, 呵呵.
笔试题大多有以下几种:
- 专业题, 计算机相关专业, 就是数据结构与算法, 树, 链表, 字符串操作居多, 外加一些操作系统, 计算机网络的基本知识. 当然,如果你应聘的是dba, 或者sa, 就有一些特殊的题目, 比如sql啊, unix命令之类的. 语言基本上就是C或者C++, 很多招聘Java的职位, 考的试卷也是C++的.这个始终让我觉得很囧.
- 能力题, 能力题大致包括逻辑题, 智力题等等. 逻辑题比较容易做. 智力题的话, 也只有题海战术了, 网上多搜搜这个公司前几年的考题就一般能够找得到.
其实笔试考的好坏也不是很重要, 如果笔试没有进, 那么你就得把笔试题记住, 然后大胆的去霸王面把! 因为霸王面一定会问你, 你考试的时候觉得做的不好的是什么题? 回来以后有没有考虑过怎么做?
四. 面试
面试我想分开来谈, 呵呵, 因为面试太多, 不同的面试方式都不一样.
不过有几个词是通用的: 诚信, 团队, 本色!
另外, 和面试官要不亢不卑, 态度谦和. 多说谢谢是不会错的.
另外, 面试某公司面前, 应该去了解这个公司的用人原则, 或者他们创始人的名言之类的, 这个会在一定的时候, 收获奇效哦!
五. 专业面试
专业面试, 关键点就是把面试官吸引到你希望他问的方向上面.
当然, 如果你不知道面试官会问你什么问题的话, 那就应该找一家公司做试验, 看看他们的面试官会问你什么. 其他的公司大多数是差不多的. 对我自己来说, 可怜的千橡就成为了我的试验品了.
从试验公司知道了会问的问题以后, 回来立刻投入准备, 必须马不停蹄. 如果面试官问的是基础知识, 回来立刻背概念, 基础知识; 如果问项目, 回来把项目代码看一遍把关键技术要点思考一遍. 当然, 最好2个都做.
事实上这一招很有效, 在整个求职过程中, 我被问了4遍TCP三次握手.. – -!
然后要做的就是每次面试以后, 不断的复习这次面试过程中没有回答出来的问题, 强化记忆. 比如我第一次遇到select和epoll的区别的问题时候没有回答出来, 回来以后详细的看了一下, 后面的面试里面又被问了3次, 就回答的很好了.
最后要强调, 基础是非常重要的, 因为靠准备是不能准备全部的知识的, 只能平时积累了.
面试官最喜欢做的事情, 就是抓着你支支吾吾回答不清的地方问. 所以遇到自己不熟或者忘记的地方, 一定要果断的说, 不知道或者不清楚. 当然, 如果他问的问题全部都不知道, 可能就应该考虑自己知识点是否存在漏洞, 在面试回来就应该好好修补一下.
关于专业面试, 其实功夫还是在场外啊, 面试最重要的也就是把面试官引导到你熟悉的地方, 其他能做的, 就是好好的回答问题吧.
六. 群面
群面, 又叫做无领导小组讨论, 或者是AC面. 就是一帮人坐在一起讨论一个问题, 最后得出结论. 考核组员的合作能力, 处理争执的能力, 以及逻辑思维能力, 细心程度等等. 考察的东西相当的多.当然注意点也非常的多.
原来还以为面技术的不需要过群面, 结果网易游戏还是给了我这个机会让我体验了一把群面的感觉.
关于群面的考核目标里面, 我没有说结论的正确与否也是考核的目标. 因为很多讨论根本就是没有正确结果的, 所以无结果, 或者结果不能让所有人满意是很正常的情况. 大家也不要对群面的结果斤斤计较. 群面, 最重要的是过程.
群面的技巧, 按我的理解, 可以总结为以下几点, 不当出头鸟, 不当末尾兵, 说话平和, 面带微笑, 多多的鼓励人, 不要多说一句废话.
不当出头鸟是因为, 讨论的过程之中, 大家会自发的形成一个小团队, 团队必然有leader, 当然, leader不是这么好当的, 因为leader是面试官关注最多的人, 任意一点表现的不好, 都会导致得分的下降, 甚至不能进入下一轮面试. 所以, 如果觉得自己能力有限, 就不要当leader, 否则必败无疑.
不当末尾兵, 是指尽量不要当总结陈词的人. 因为总结的人对于其总结能力, 逻辑思维能力的要求非常高, 如果因为总结而导致逻辑错误, 或者说话支支吾吾, 等等状况的出现, 都会让面试官给你减分.
说话平和, 是说语气要平缓, 不急不躁, 让人听清为准, 不能像吵架一样语无伦次.
面带微笑, 这个是基本常识了.
多多鼓励人, 就是比如当主持人说, 请大家评价一下某位同学, 或者说, 大家评价一下这次面试的时候, 一定要说好的地方. 比如, 这位同学能力很强, 或者说, 某某同学时间控制的很好, 用正面的眼光去看人.
不说废话, 不是说不要当说话最少的人, 而是说说的话必须在点子上. 当整个队伍都是强人的时候, 很可能你的观点是和别人相同的, 这个时候可能就会觉得很尴尬, 自己的话都被别人说了. 那么, 着眼点就可以放在其他地方而不是结论的得出上. 比如, 提醒大家一些细节的小地方等等. 或者, 调控场面气氛等等.
群面其实还是比较能够测试一个人的性格特点的, 面试的时候什么状况都会出现, 大家记得保持冷静就是了.
最后再次强调, 谢谢不离口, 时刻保持微笑.
七. HR面
HR面往往是面试的最后一关, 一般来说, HR只有否决权没有决定权, 所以只要不犯大错误, 基本上offer就到手了.
HR面试的问题, 一般就是你的人生规划, 你最得意到事情, 最失意到事情等等, 大家到应届生网站上面可以查到一堆到问题. 所有问题到回答总结起来就是一句话, 千万不要和HR交心(借用浩哥的原话, 嘿嘿).
因为HR毕竟还是代表公司的, 如果这个时候放松了警惕, 说了一些不该说的话, 最后失意的也只有自己.
所以, 谈论自己缺点等等的时候, 就放一些无关紧要的缺点, 万金油的回答就是, “我觉得我的缺点是学习的东西偏重理论, 实践经验不足”. 这句话真是屡试不爽啊..大家一定要从中看到WS的地方, 深刻领悟之..
另外, HR面还会看你是不是真的想要去他们公司工作, 如果你面试阿里巴巴, 言必谈及马云曾经说过blahblah, 我想, HR那里你的好感分会大大的增加.
还有一点要注意, HR面的时候, 你得时时刻刻表现出自己是团队的一份子. 比如说你最得意的项目之类的, 就一定要举出一个团队合作的例子, 尽量少搞个人英雄主义, 那是20年前的事情了.
要注意的是, 最后结束时候HR会问有没有问题要问我, 别忘了面试还没有结束, 你还是要表现自己非常想去他们公司, 还是有一个万金油的回答, “如果我拿到offer, 能不能马上过去实习呢”
哈哈, HR面一定要脸皮厚啊, 大家千万记住哦. 这是黎明前的黑暗, 光明就在眼前.
八. 感谢
好吧, 真心的感谢这段时间来给我鼓励, 陪我渡过难忘岁月的朋友们. 你们都是我的好兄弟或者姐妹. 以下感谢名单排名不分先后.
浩哥, mapx, 老万, 张师傅, reck, 老邓, 刘姐姐, 子, 波波, 小胖, 小威等等…以及所有帮助过我, 鼓励过我的人!
再次表示衷心的感谢…肺腑之言啊!
最后, 祝愿所有还在为了自己的理想奋斗的同学们, 加油! 要坚信, 自己一定会成功的.
优化Python的DES加密程序有感
此文来自本人原JavaEye博客,发表时间2009年3月24日,可能有些东西现在看来是过时的,甚至是错误的,不过为了保证原来写的时候的感觉,所以没有修改。只在括号中注明了现在的看法。原文地址
最近信息安全的老师布置了作业。要求实现DES算法。。写了1天,优化了1天。。。小有些心得。。
首先感慨一下DES算法。。真是对人对机器都不友好的算法。。竟然还有诡异的S-BOX操作。。。
第二感慨一下Python对2进制不那么方便的支持。。连bin函数都没有。。虽然3.0有了。。可惜2.5没有。。只能自己实现,一大损失效率的地方啊。
好,接下来说说优化过程。
首先是单线程改多线程。。原来是将明文分成64bit一块的序列,每块单独加密。改成每一个64bit的块开一个线程操作。(这个在今天看来完全搞笑)
单线程加密解密一个1000长度的字符串所需时间大致和多线程加密10000长度的相等。效率提升明显。(提升效率很奇怪,忘了自己当初怎么测试的了)
其次是优化异或过程。原来的异或是整体将字符串转成整数然后再异或,发现效率很低。第一次修改为将2个字符串的每一位单独取出转成整形以后异或,效率提升不明显。后来上课时候突然想到,异或操作其实完全可以抛弃整数。1位的2个字符串的异或操作只有4种,写一个字典,用想要异或的2个字符串作为key,结果作为value。简单实现了一下。
def Xor(s1, s2):
"""
字符串xor
s1 -- 第一个字符串
s2 -- 第二个字符串
"""
data={}
data['0','1']=data['1','0']='1'
data['0','0']=data['1','1']='0'
s=[data[s1[x],s2[x]] for x in range(0,s1.__len__())]
return ''.join(s)
三就是优化10进制转2进制。因为python没有提供 bin 函数。于是自己实现了一个。
dec2bin = lambda n:''.join([hex2bin(x) for x in hex(n)[2:].rstrip('L')]
但是在用profile做测试的时候发现的。程序运行中大量的用到了这个函数。很占cpu时间。经过观察发现主要是2个地方使用很多,第一就是异或操作的时候,因为python提供的异或只能在整数之间进行,第二就是在S_BOX运算的时候。
异或操作已经优化了。不需要10进制转2进制了。。剩下就是S_BOX运算了。经过观察发现,S_BOX里面最大的数也不过 15,于是想到可以穷举所有S_BOX里面的数字的值对应的二进制。更改代码如下。
def easyDec2Bin(s):
"""
简单的10进制转2进制,用于简化s_box操作
s -- 10进制数
"""
data={0:'0000',1:'0001',2:'0010',3:'0011',4:'0100',
5:'0101',6:'0110',7:'0111',8:'1000',9:'1001',
10:'1010',11:'1011',12:'1100',13:'1101',14:'1110',
15:'1111'}
return data[s]
第四步优化也是通过profile发现的。。发现程序运行过程中,大量的时间消耗在一个lambda函数上。
b= ''.join(map(lambda x:data[x],s))
这个函数的作用是生成一个字符串。。尝试着把这个lambda函数改成列表操作。
b= ''.join([data[x] for x in s]
效率提升明显。。。原来一直以为map操作比较快。看来并非如此。难怪Guido大叔要推广列表操作了。。
最后一步优化就是用了psyco模块,将程序变成JIT的。。效率提升很大。。。(现在看来其实这一步是最关键的。自己当初好傻)
最终优化的结果就是,加密解密1个40k的文件,原本需要将近50秒的时间,现在10秒不到就完成了。。。。
效果提升明显。不过总觉得还有提升的空间。。尝试把多线程改成Stackless版本的试试看。。。。希望能有更大的提高 。。。。(这句话现在看来完全是搞笑,看来当时的自己还是很稚嫩啊)
Django的Middleware开发有感
此文来自本人原JavaEye博客,发表于2009年2月26日。原文地址
Django应该算是目前最火的Pyhton的Web框架了把。个人感觉,超级方便的ORM,清晰而功能明确的分层以及Killer级别的后台管理都让习惯了Java那一套庞大复杂的人有了眼前一亮的感觉。
不过用久了就会发现,django整个框架之中有一个极其繁琐的地方,就好像一块整洁的布上有一个污点一样,令人觉得不爽。
那就是他的URL机制。。当然,也有人非常喜欢他的URL机制,比如说十分的灵活。不过我个人总觉得还有改进的地方。
首先我认为必须要利用正则表达式这一点,这个是特色以及精华,并且确实十分方便,在我眼里属于不能更改的部分。那么自然而然改进的地方就是正则表达式和函数的映射了。
提出问题是一方面,解决问题就是更加重要的地方了。采用何种新的方式来替换原来的URL处理呢?我为此困扰了好久。直到有一天发现了limodou大牛的Uliweb框架。被它的简洁明了的URL方式吸引了。决定采用类似Uliweb的方式处理URL。实现的具体细节,就是用Django的中间件。
使用中间件自然有他的理由。研究官网的文档后发现,Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。所以说我们要做的就是在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response。需要注意的是,因为我不舍得放弃Killer级别的Admin,所以必须要支持默认的URL配置方式。那么我们可以简化原来的设计思路,把中间件不能处理的Request统统不管,丢给Django去处理。简直是完美的解决方案。:)。同时也不得不赞一声Django的设计。
接下来的设计就是考虑URL和函数处理的问题了。这个时候应该感谢的就是Python强大的语法了。提供了Decorator这种机制来解决这个问题。那么设计的思路转变成,在Request到达Middleware的时候,Import所有INSTALLED_APPS里面的views.py,目的自然就是执行Decorator。而在Decorator内部,根据到达的Request获得其访问地址,然后和处理它的函数一起生成RegexURLPattern对象,储存在缓存中。然后对每个Request进行处理,符合规则的就调用函数处理,不符合规则的,就交给Django自己去处理了。
以下是一小段中间件代码。比较核心的部分了。其实代码量也不大。大家看看有没有实现的问题。
def process_request(self,request):
path=request.path_info #获得request的地址
urls=settings.INSTALLED_APPS #获得当前安装的app的位置
def myimport(path):
try:
__import__('%s.views'%path) #读取所有app的views。。目的是注册request处理函数
except:
pass
map(myimport,urls) #执行所有
callback=expose.getCallback(path) #获取相应url对应的处理函数
if callback:
return callback[0](request) #执行。。
整体设计大致如此,完成了0.1版本,已经放在我的代码库里面了.http://code.google.com/p/linllx/
目前还存在的问题就是。第一,对于需要命名分组的正则表达式的处理还不是很有头绪。第二,对于404错误的处理究竟要如何进行,目前的实现来看不是很好。请看见本文的牛人们提供一下思路。。
总得来说,Django中间件的开发并不像我想像中的那么难,甚至可以说,还是比较简单的。下一步着手开发一个类似于Java中的Filter的中间件把。。当然,这个还是需要继续完善的。。
使用greenlet中一点简单心得
想要对greenlet的switch机制进行测试,于是写了以下这段代码。
from greenlet import *
def test1(x, y):
print 'in test1'
z = gr2.switch(x+y)
print z
print 'out test1'
def test2(u):
print 'in test2'
print u
gr1.switch(42)
print 'out test1'
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch("hello", " world")
运行结果:
in test1
in test2
hello world
42
out test1
从这个层面可以看出。greenlet的协程其实是一个切换机制。就是主动将自己的运行过程让给别的协程。切换需要有目标,并且可以在switch里面传入参数。如果是第一次运行,switch的参数就是作为协程的run的函数的参数传入。如果是运行中,就作为switch的返回值。
以上隐含的内容是,如果在运行中想要切换到别的协程去做事,那么不能保证那个协程一定会返回结果。
考虑在greenlet上面加上一个隐含回复机制。