晒晒我的开源项目们

October 6th, 2011

在等“bundle install”的时候闲着没事,打开 我的Github ,发现还有那么一些东西值得分享一下的。

啤酒游戏 :《 第五项修炼 》里讲的啤酒游戏。多人协作游戏,适合培训时候用。培训详情请联系 小刀

合作的进化 :这就是《 合作的进化 》那本书里讲的生存竞赛游戏。可以自己写新的策略放进来,看看重复囚徒困境中的最佳策略是如何被选择出来的。

Jungling :作为技术人员的TWer到客户现场启动一个新项目时需要注意哪些事?带上iPad和Jungling,你的丛林冒险手册就有了。

每天一小时1.HourFor.Me 的源代码。每天一小时,每月就能做成一件事。欢迎贡献,如果从代码里发现了漏洞,还望高抬贵手请勿攻击。

TRSSTRSS 的源代码。 把RSS同步到新浪微博(因为新浪自己的同步功能貌似不工作了)。后面还可以有很多发展,例如同步到各种微博之类的。同样,欢迎贡献代码,多谢请勿攻击。

jquery.image-preview :一个比较体面的图片预览插件,实现就像Google Images那样的 效果 :鼠标悬停在小图片上,小图片就会放大预览。主要的难点是当小图片位于页面边缘时,预览也要出现在合适的位置。

图灵机 :这两天开始写的,照着 图灵的论文 ,用 Clojure 实现一个原模原样的图灵机。后面也许还想在iOS上实现一个有图形界面的。

发现我的开源项目们有个共通的问题:虎头蛇尾。每个点子都没有耐性深挖下去。想写代码练手的年轻同事们可以找我啊,我这里要干的活很多的⋯⋯

问题

当一个JavaScript计算进程耗时太长,浏览器会弹出警告框,不仅烦人而且一不小心就会点错导致后面的程序不被执行。

很多这类长计算是由于操作大数组造成的。虽然每个元素的处理耗时很少,当数组有几百上千个元素时整个计算时间就会长到超时。由于数组元素数不确定,对单一元素操作调优仍然不能根本解决问题。

办法

把长计算拆解成多个异步的短计算。

即使计算所需的总时间并不缩短,将阻塞的长计算拆解成异步的短计算至少带来响应性的提升:在计算进行的同时用户还可以做其他操作,而不是眼看着整个浏览器失去响应。

在拆解的基础上可以改进任务分发机制以提升整体计算时间。

步骤

  • 重构原来的长计算
    • 把整个长计算抽取到一个方法中
    • 重构该方法使之呈现以下结构:
function longCalculation() {
  before();
  var items = getItems();
  items.each(handleSingleItem);
  after();
}
  • 把循环重构为递归
    • 把“操作数组中所有元素”的逻辑抽取到一个递归调用的方法,使之呈现以下结构:
function handleItems(items, cur) {
  if(cur == items.length - 1) {
    after();
    return;
  }

  var item = items[cur];
  handleSingleItem(item);

  handleItems(items, cur + 1);
}

function longCalculation() {
  before();
  var items = getItems();
  handleItems(items, 0);
}
  • 把针对每个元素的操作变成一个异步的计算进程──这一步很简单,只要在调用handleItems方法时始终加上delay就行。

以上。应该很容易写出一个类似于library的玩意来封装这个模式。太容易了以至于我不想写。

JavaScript跑太久…

July 2nd, 2008

IE就瞎菜了…傻了吧唧的蹦出来问“好像浏览器上有个操作死菜了,咱把它干翻吧?”烦人还是小事,十有九个人会点“Yes”,然后就真干翻了…

(根本原因是IE6/7不支持XPath,于是只好遍历DOM来找东西,which is非常慢啊…从一个500K+的DOM里找到一堆东西,Firefox只要几十毫秒,IE6要用到1秒…)

(试了一下 JQuery的CSS selector ,搞了个折中,IE6和Firefox都一百多毫秒,然则还是不够…几组查询下来IE还是瞎菜了…)

于是用空间换时间,在page上建索引。然则还是不行,因为最耗时的操作不止这一个…

于是把耗时的操作摘出来,原本都在onload里做的事情放在DOM loading的过程中,变成几百个小块来做。最耗时的两个操作,组装过滤列表和查询,用setTimeout变成异步的。

(这个时候很得意的问 郑晔 :“阻塞操作太长怎么办?”得到答案:“搞成异步的。”)

然后一边唱着“牛x闪闪放光芒”,一边就发现break了另一处的功能…这个组件是被很多地方以很多方式重用的…

紧接着伤心地发现这块JavaScript已经非常混乱而难以理解了…重构迫切需要中…多想用JavaScript搞出如同Erlang一般优雅的并行计算序列啊…

(为什么每次感到很牛x的时候总会紧跟着很失落的发现有一大堆破事搞不定呢…这就是程序员的宿命吧…)

两个tricks

June 16th, 2008

今天遇到两个tricky的东西,记下来。

1. 把十六进制数写到字符串里。

[0xEF, 0xBB, 0xBF].pack("C*")

(这个是 UTF8的BOM ,写在文本文件比如CSV的头上就可以让读取的软件比如Excel知道这是UTF8编码的文件。)

2. IE窗口的滚动条如果鼠标点下去也会触发 document.onclick 事件,而Firefox就不会。

(不明白为什么滚动条也可以算作document的一部分。)