qyb的博客

FireBug 1.0 !

这个月三个重量级的产品发布了新的里程碑:jQuery 1.1,prototype 1.5,然后就是 FireBug 1.0

其实我也就是最近才偶尔用用 FireBug,不过还是觉得这玩艺深深改变了以往调试 JS 程序的方式。Internet Explorer Developer Toolbar 好不容易赶上了 DOM Inspector + Web Developer 的功能,但又远远被 FireBug 落在了身后。

如果有工夫的话,倒是想着利用 python 给 IE 做一个开发用的插件,实现 HTTP Watch 的功能

Topic: 技术

Apache2 Module 开发后记

没有接触 Apache Module 开发的人可能觉得这是一个很深奥的事情,其实对于有一定经验的人来说还是挺简单的。当然最好是有这么一个环境,一些"SMTH系"的人的 blog 时常会提到什么什么时候又写了一个 Apache Module,语气犹如吃饭睡觉一样稀松平常;深受清华影响的 SOHU 也是如此,动辄就会有个人跳出来和你讨论某样业务如果用 Apache Module 来实现会如何如何,久而久之,就会在思维深处认为写 Apache Module 简直是天经地义。

1. 最通常的用法就是 ap_hook_handler. 这里是 http request 处理的最后时期。而且注册的所有的 handler 都会执行一遍。我做的模块的最核心的流程就是在某些条件下增加一个 HTTP Header 交给最终的内容处理引擎(比如JSP/PHP之类);以及设置一个 Response HTTP Header 项,当 Apache 开始向浏览器返回 Response 的时候,会把我这里添加的项目也输出出去。

2. ap_hook_handler 会应用于所有的请求,有些时候会显得效率有些低——比如对静态文件就没有必要执行额外的处理,这时候用 input_filter 可能会比较好。通过 AddInputFilter 可以设定对某些 Directory/Location 才执行对应的 filter 操作。不过据说 filter 应用也有一些效率问题,需要做详细的 benchmark 才能有结论。

input_filter 的另一个用途就是保持长连接,比如 webim 就可以通过这个方式来实现 Server 端的业务。

3. post_config 阶段可以用来检查运行模块所需要的参数是否都在 httpd.conf 里面被正确配置了。不知道 Apache 的人出于什么样阴暗的心理,post_config 会被执行两次!?这里有人提出了解决方案,如何确保自己的代码只运行一次,而不至于在 error_log 里面留下连续两行同样的LOG如同可笑的弱智bug。

由于我写的这个模块将会被部署到很多台很多台服务器上,万一哪天需要更换模块就需要找出所有部署的系统进行更新。于是每次 Apache 启动后会向一台中央服务器发送一条记录,通知该服务器维护人员的联系方式。这个流程也放在 post_config 阶段,此时 Apache 还没有 spawn 子进程,如果连接并发送记录花很长时间的话会影响 Apache 的正常服务。通常的思维是发 UDP 包出来,但这样的话需要额外写一个 UDP Server 接受它们,于是我在模块里面无耻的 fork 出一个子进程,利用 APR 提供的 socket 函数,大概 10 几行代码就搞定一次 HTTP 请求,然后马上 exit

Topic: 技术

openssl speed

使用 openssl speed [value] 可以测试某项算法的执行速度。

可以直接执行 openssl speed rsa,让他依次去计算 512bit、1024bit、2048bit、4096bit 的效率;也可以单独执行 openssl speed rsa512 来算。

在 PIII 700 上的结果为

                  sign    verify    sign/s verify/s
rsa  512 bits   0.0021s   0.0002s    475.4   5199.0
rsa 1024 bits   0.0102s   0.0005s     97.7   1883.4
rsa 2048 bits   0.0592s   0.0017s     16.9    582.2
rsa 4096 bits   0.3912s   0.0055s      2.6    181.9

speed 参数还支持 -multi n 参数来进行并发操作。在 PIII 700 双CPU 情况下并不是成倍增长,很奇怪。不过可能因为那台机器当时还有其他负载的缘故。

按照《应用密码学》里的建议(Applied Cryptography),2007 年企业应用应该考虑 1536bit,但 openssl speed 不支持1536bit的benchmark,于是自己写了一个程序来计算效率。

  1. /*
  2.  * openssl genrsa -out rsa1536.key 1536
  3.  * openssl rsa -pubout < rsa1536.key > rsa1536.pub
  4.  * gcc -o benchmark benchmark.c -lcrypto
  5.  *
  6.  */
  7. #include <unistd.h>
  8. #include <signal.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <openssl/rsa.h>
  12. #include <openssl/pem.h>
  13.  
  14. int global_flag = 0;
  15. void signal_alrm(int sig)
  16. {
  17.     global_flag = 1;
  18. }
  19.  
  20. int main(int argc, char *argv[])
  21. {
  22.     char *buf;
  23.     int size, ret;
  24.     FILE *pubfp;
  25.     FILE *prifp;
  26.     RSA *pub;
  27.     RSA *pri;
  28.     int i;
  29.  
  30.     OpenSSL_add_all_algorithms();
  31.     ERR_load_crypto_strings();
  32.  
  33.     pubfp = fopen("rsa1536.pub", "r");
  34.     prifp = fopen("rsa1536.key", "r");
  35.     pub = (RSA *)PEM_read_RSA_PUBKEY(pubfp, NULL, NULL, NULL);
  36.     pri = (RSA *)PEM_read_RSAPrivateKey(prifp, NULL, NULL, NULL);
  37.     fclose(pubfp);
  38.     fclose(prifp);
  39.  
  40.     if (pri == NULL) {
  41.         printf("PEM_read_RSAPrivateKey error\n");
  42.         ERR_print_errors_fp(stderr);
  43.         return 1;
  44.     } else if (pub == NULL) {
  45.         printf("PEM_read_RSA_PUBKEY error\n");
  46.         ERR_print_errors_fp(stderr);
  47.         RSA_free(pub);
  48.         return 1;
  49.     }
  50.  
  51.     size = RSA_size(pri);
  52.     buf = (char *)malloc(size);
  53.  
  54.     signal(SIGALRM, signal_alrm);
  55.     alarm(10);
  56.     i = global_flag = 0;
  57.     while (1) {
  58.         if (0 == RSA_sign(NID_md5, "0123456789abcdef", 16, buf, &ret, pri)) {
  59.             printf("RSA_sign error\n");
  60.             ERR_print_errors_fp(stderr);
  61.             free(buf); RSA_free(pub); RSA_free(pri);
  62.             return 1;
  63.         }
  64.         i++;
  65.         if (global_flag) break;
  66.     }
  67.     printf("RSA_sign: %d\n", i);
  68.  
  69.     i = global_flag = 0;
  70.     alarm(10);
  71.     while (1) {
  72.         if (0 == RSA_verify(NID_md5, "0123456789abcdef", 16, buf, ret, pub)) {
  73.             printf("RSA_verify error\n");
  74.             ERR_print_errors_fp(stderr);
  75.             free(buf); RSA_free(pub); RSA_free(pri);
  76.             return 1;
  77.         }
  78.         i++;
  79.         if (global_flag) break;
  80.     }
  81.     printf("RSA_verify: %d\n", i);
  82.  
  83.     free(buf); RSA_free(pub); RSA_free(pri);
  84.     return 0;
  85. }

10秒种内 sign/verify 一个长度为 16 位的字符串结果如下:
PIII 700 330/8680
XEON 2.4G 666/17034
XEON 3.0G 799/22633
XEON 5130/2.0G 1053/29154
感觉这样的效率还是不错的,需要在实际系统中进一步小心的验证。

还有就是 openssl 编译优化的问题。为了测试 ECC 的支持,我自己编译了 openssl-0.9.8。结果发现在计算 rsa512 的时候,我编译的 openssl(采取缺省configure) 比系统缺省的 openssl 慢了 10% (470 vs 420)。改了改config,可以提升到 450 左右,后来就没有再仔细琢磨下去。

最后用 openssl 0.9.8d 测试了一下 ECC 的签名校验效率(ECDSA),执行 openssl speed ecdsa (PIII 700)

                              sign    verify    sign/s verify/s
 160 bit ecdsa (secp160r1)  0.0013s   0.0061s    786.1    162.9
 192 bit ecdsa (nistp192)   0.0013s   0.0062s    774.7    160.4
 224 bit ecdsa (nistp224)   0.0016s   0.0079s    616.5    126.4
 256 bit ecdsa (nistp256)   0.0020s   0.0101s    503.8     99.0
 384 bit ecdsa (nistp384)   0.0046s   0.0249s    218.5     40.1
 521 bit ecdsa (nistp521)   0.0097s   0.0519s    103.0     19.3
 163 bit ecdsa (nistk163)   0.0046s   0.0125s    219.8     80.3
 233 bit ecdsa (nistk233)   0.0090s   0.0240s    110.7     41.6
 283 bit ecdsa (nistk283)   0.0140s   0.0447s     71.5     22.4
 409 bit ecdsa (nistk409)   0.0315s   0.1063s     31.7      9.4
 571 bit ecdsa (nistk571)   0.0705s   0.2507s     14.2      4.0
 163 bit ecdsa (nistb163)   0.0046s   0.0133s    218.8     74.9
 233 bit ecdsa (nistb233)   0.0091s   0.0268s    110.3     37.3
 283 bit ecdsa (nistb283)   0.0141s   0.0506s     71.2     19.8
 409 bit ecdsa (nistb409)   0.0316s   0.1224s     31.7      8.2
 571 bit ecdsa (nistb571)   0.0704s   0.2877s     14.2      3.5

签名速度还可以,就是校验速度慢死了..

Topic: 技术

搜狐技术年会

搜狐这次的技术年会在京东思菩兰度假村召开。总共去了大约 230 人,周五下午出发,很快就到了。晚上年会,然后各自活动到半夜,第二天早饭后继续运动,午饭后杀回公司。

年度 MVP,刚来搜狐的时候就结识了,在这篇 blog 里面说的 guru 就是他,不算太出乎意料。

年度新人之一最近也打交道比较多。刚开始接触的时候知道他在维护 chinaren 的 Apache Module 的开发;前不久看他在很专业的用 FireBug 调试 JS,立刻吃了一惊。加上他 Emacs 用的超熟,相当让人叹为观止,真是"沉舟侧畔千帆过"。这次得了最佳新人让我稍微平衡了一些——这么强悍的小孩并不是到处都是的。

以家属身份参加过两次瞬联的年会,搜狐的节目稍微单调一些,就只是把几位领导架到台上玩弄一番,呵呵。

老板也赶来做了个发言,不过很多内容在以前内部会议的时候就听过了。总体来说他现在的思路是很偏重技术的,而且老是把 Yahoo 的管理层拿来当反例,认为互联网和 MBA 教派几乎是背道而驰。关于这方面俺就不具体评论了,呵呵。

在度假村内的休闲时间我完全放在了乒乓球台上。发现自己居然还能打得有模有样,hoho,而且这种低烈度无身体对抗的运动很适合俺的老胳膊老腿的。

周六回到公司,从四环保福寺路口向北拐以后,立刻看到清华科技园8号楼启迪科技大厦(网易北京也在里面)新装上的"Microsoft"标志,非常醒目。搜狐的邻居们是越来越有趣了。

Topic: 生活

做一个半瓶子 Javascript 程序员

最近项目需要一部分 javascript 代码做 DOM 操作,并且最终是要提供给其他项目调用的。组内的其它同事对 JS 不算精通,虽然 Web 前端开发咱不专业,但好歹有幸和 Lewisrealazy 两位高人同事过,这就叫没吃过猪肉也看过猪跑,于是承担起代码初始编写的任务。

过程很简单:首先是根据需求写了大约 1100 行可以工作的代码,交付给第一个用户 todd,然后俺按照他的建议花了大约1天半的时间把代码改写了一遍,剩下最后的逻辑和界面剥离的任务交给别的同事完成。

以前也用过 javascript,这次才真正以开发产品的目的来写代码。(伪)静态类、函数式编程、闭包这些概念首次接触到,感觉 Javascript 是一门很严肃的程序设计语言,要想掌握或者说精通绝对是一个挑战。具体到 Javascript 在浏览器环境(DOM/HTML)的运行就更需要经验了,好比把 Linux 程序移植到 Solaris 和 AIX,总会在一些细微的地方有什么东西会跳出来捣乱。

假设你已经很熟悉一门开发语言了,由于某些原因需要做一点儿 Javascript/AJAX 开发,那怎么开始呢?

1. 从根本上要重视 Javascript 语言。相比较服务器端主流的 C/C++/Java/PHP 而言,Javascript 属于动态语言(在对 Python/Javascript 有了一些初步了解后,我发现严格上来说 PHP 都不能算动态语言),我认为只有掌握了语言的精髓才能写出好的代码。

2. 需要一个好的调试环境。至少现在为止,Firefox + FireBug 的组合应该是无人可敌的吧。

3. 参考手册。MSDN 和 MDC 上都有很好的在线文档。我个人偏好 MDC,包括 Gecko DOM ReferenceCore JavaScript 1.5 GuideCore JavaScript 1.5 Reference。微软还有一个中文的离线文档 jscript5.chm,似乎是随着 Office 2000 一起安装的,网上很多地方提供下载。

4. 学习别人的代码。prototype 是一个很好的起点。

今天刚刚发现一个更简单的代码集合,里面包括"$ function, getElementsByClassName, event handling, the JS 1.6 array methods, and the DOMContentLoaded event",如果 prototype 看的头大,可以先把这个看明白再说。

除了 prototype 外,JQuery 偏重于 DOM/CSS 特效,被视为 prototype 有力的竞争对手。

5. 补充读物。推荐 deanppk 的 blog。

成为一个 JS 半瓶子程序员并不是太难达到的目标。:)

Topic: 技术

Will you still love me tomorrow.

早上一醒来,发现宝宝已经睁大眼睛在想事情了。

突然她长叹了一口气,说:“我好爱妈妈啊”

我问,“那爸爸呢?”

她说:“我明天再爱吧”

hehe. 真好玩.

Topic: dada 生活

买房

老婆工作的地方据说夏天就会搬到望京,加上我大约也会长期混迹在中关村,因此买房这个事情就再度提上了我家的议事日程。

首先关注的是华清嘉园,因为就在搜狐附近,而且有中关村二小。查询之下很令人沮丧,华清嘉园北京二手房涨幅第一,最近成交均价14,000,实在是没有搞定的底气。好玩的是在 focus.cn 上看到一个署名 wang_xiaochuan 的人也在求购华清的二手房,看留下的手机号,的确就是王总,呵呵。

排除了华清嘉园,基本上也就放弃了找个海淀好小学附近的方案,那样就太靠西边了。估计春节后每个周末就要出去淘房了。

不知道还有哪位朋友也计划在北边买房?有好房源请告诉我,不胜感激。Orz

Topic: 生活

sohu 新闻页面正在向标准化过渡

上次开会就听说将以 DIV 进行布局,今天上班来看了看,不错,已经是 1024x768,声明了 DTD 文档类型,webdeveloper 不再提示 quirks mode 了。不过奇怪的是首页还是老样子,希望能早日改进。

另外今天读到一篇挺有意思的文章:老曹硬了 谢文走了 张朝阳笑了. 里面提到搜狐6大派系。hehe,以后注意观察观察。

搜狐的技术部门似乎是当初 ChinaRen 的班底,倒没有什么派系,就是人多项目多,沟通上差了一些,如果知识能更有效的散播就好了。

PS: 前不久被提醒,chinaren 的老大邹丹就是最早破解出 QQ 协议的人,当初还真没把这个名字对上号,记忆力衰退啊.

订阅 RSS - qyb的博客