June 9th, 2009IE的怨念

– 因为写网页发现很多不兼容的郁闷的地方……

1. 数组声明

var a = {a: 1, b:2, c:3, }

注意最后一个”,”, 这样写在ie里是会报语法错误的……

2. 上面的例子, 如果没有初始化列表的最后一个逗号在ie中是可以的, 但是下面的呢?

var params = {class : “main”, a : 1};

在网页里写下这样的代码, 然后拿到ie里运行, 貌似没看出啥问题(我用的IE7), 可是你会发现你的代码为啥总没执行呢? 于是一行一行的删除代码, 最后n长时间过后总算发现是这行代码的问题, 可是为啥呢? 仔细看看, 貌似这里特别的地方就是在初始化列表里的class是一个关键字 — 是的, 就是它了, 对于有这种关键字的初始化列表是要加上双引号的, var paramrs = {“class” : “main”,  a : 1};, 这个问题很恼人 — 你支持{a : 1};为啥就不支持{class : 1};总感觉这里的实现像是半个残废.

3. css兼容性的问题, 太多了…… 导致看到好好的东西到了ie下就是不中啊, display:table-cell 在ie8之前的版本里不支持, 我哭.

4. 再另外像inject <tr> 到<table>里不工作, 必须得先把<tr> inject<tbody>里才行, 用的是mootools, 但估计也是IE的问题导致的, 反正是有了怨念, 就把这个也算到它的头上吧.

用javascript写程序, 想不到使用的感觉不错, 对js萌生出不少好感来, 有了好感后便是想着能在所有的地方用它, 于是便yy能在写本地程序的时候也用上js — 如果写本地程序可以用像写网页的方式写下来, 那该多完美哪 (当时yy的是一个程序可以以native/网页的形式运行的东西~~~). 记得当时找了一些, 貌似没有太多收获, 今天偶然又google了一把, 居然找到了一篇有趣的blog介绍gtk Seed, 果然有点意思.

Seed是个什么东西, 它的主页上有了介绍, 它是一个库, 解释器以及可以在运行时和webkit javascript核心引擎协作的东西.一句话它提供了你创建本地javascript程序的能力. 这个项目比较新的, 2008年11月8号才发布第一个版本. 这里有篇blog给了一些用它实现的小程序, 看上去还不错, 它封装的本地gtk api应该基本够用了, 没有仔细研究, 但至少文件/窗口消息啥的都有了. 另外貌似这里还用到了Gobject Introspection, 貌似很牛X的, 这个东西的目标之一应该是使用系统语言(像C之流)写的Gtk对象的窗口对象可以不经过任何额外的封装操作都都可以在其他语言中使用(像python/javascript) — 这样还是比较方便的. seed主页可以找到很多例子程序, 看了几个, 貌似很方便. 抽时间了搞下来折腾一下, 不知道有没有提供windows下的版本…

另外与Seed类似的还有另外一个项目:GJS, 这两个引擎的目标都很相似, 貌似都是为了提供本地化的开发能力, 区别就是Seed采用了webkit的js 核心, 而GJS则是使用的mozilla firefox的js引擎(Spidermonkey ). 使用spidermokey引擎的好处之一据说就是可以使用很多webkit中尚不支持的javascript5中引入的新语言特性. 不过看了一些文章, 似乎Seed和GJS的老大们还有过一些讨论目的是使得这两个引擎提供良好的兼容性, 其中Seed的老大似乎还同意修改Seed中Enum/import的实现以保持和GJS的一致.  不过相比较而言似乎Seed项目相对比较活跃一些, 更新比较频繁, 今年已经发而了五六个版本. 而GJS则相对比较沉闷了一些了, 似乎这半年没啥动静, 有点怀疑是不是要黄了……

另外既然讲到本地化的javascript开发, 就不得不提到adobe 的AIR了, 这个应该是和我原来yy的比较相似, 它支持html+js的本地程序, 看了一些文档, 提供了一些本地化的api(文件啊, 剪贴析啊之类的), 不过相对于前两者来讲应该是对于开发的限制应该多了不少. 但是这个酷在确实做到了web+native的双向执行啊, 另外就是它的开发工具相对全一些, 但是要收费滴.再另外就是Air的linux版本是incomplete的, 所以有些功能可能还是不支持地. 当然前面的两个有没有windows/mac的版本还不知道呢:)

May 15th, 2009ie css selector issue

最近写了一些html, 遇到一个很郁闷的问题, 大致是下面的, 我写了一些链接, 大致如下:

<a class="actionlink" onclick=’myfunction(this);'>mylink</a>

为它写了一个css, 如下:

a.actionlink {

    display:block;

    text-decoration: none;

    color:  #62C2CC;

    outline: none;

    }

a.actionlink:hover {

    display:block;

    color: blue;

    text-decoration: underline;

    }

a.actionlink:visited {

    display:block;

    color:  $62c2cc;

    }

a.actionlink:active {

    display:block;

    color:  red;

    }

链接在firefox下面显示的完全正常, 可是在ie7/8下却死活无法正常显示在鼠标移上去时的颜色, 网上找了很久, 看到一些相关的ie8的bug, 像css selector的问题, 这里有一个列表, 本来以为其中的一个css子对象选择符的bug是这个有关, 但是我已经把它改成了直接的类, 所以应该不是那个问题.

两天郁闷的尝试都没有成功, 今天再看相关的文档, 在看到选择符的时候, 偶然看到这么一句:

The document language determines which elements are hyperlink source anchors. For example, in HTML4, the link pseudo-classes apply to A elements with an "href" attribute. Thus, the following two CSS 2.1 declarations have similar effect:

a:link { color: red }
:link  { color: red }
这回忽然注意到其中红色的部分, 难道真和这个有关? 于是试着加上href="#", 之后, 果然一切都好了!……
<a href=”#” class="actionlink" onclick=’myfunction(this);'>mylink</a>

April 22nd, 2009闵行体育公园

传说中闵行体育公园是一个大型免费的体育主体的公园, 昨天去了一下, 感觉确实很不错, 园子很大, 环境很不错, 随便搞了些图片来, 贴一下:

April 22nd, 2009闪屏问题

今天又接到了一个问题:-| 最近的问题有点多哈!

问题是这样的, 朋友的一个程序(VC++编写)它会在上面显示一个背景图片和自己绘制的一个计时的时间显示表, 程序在开发的阶段运行一切正常, 但是客户反映讲此程序运行的相当不稳定, 总是在过了一段时间后会出现背景变灰, 并且窗口界面开始不停的闪烁. 朋友经过测试也发现有类似的状况, 在朋友的机器上程序大概运行三分钟后就会出现客户说的情况, 据朋友描述说有时也两分钟左右就会出现闪烁的情况, 只是这种情况比较少, 但三分钟是一个比较保险的使问题重现的时间.

刚听到这个问题, 比较没有头绪, 找不到问题, 于是让朋友把相关的代码发过来, 看了代码心中大概有了一个概念:

  1. 界面完全是由自己的代码绘制的,
  2. 为了显示计时器的时间, 在代码里加了一个计时器, 并在onTimer ()时重新绘制整个窗口
  3. 绘制时钟是通过装载对应的位图绘制数字的

看到这里, 心里大概能猜测到了一个可能的原因: 句柄泄漏, 一想到这一点, 所有的问题都可以解释了: 极有可能是在窗口绘制的代码里出现了句柄泄漏的情况, 在刚开始的时候没有问题, 但由于每秒钟都会定时绘制一下界面, 所以随着时间的推移, 泄漏的句柄数越来越多 — 这样当所有可用的句柄都泄漏完之后, 当再次尝试申请句柄资源以创建相关的位图对象的时候就会失败, 这样就会导致画不出相关的图片来, 于是整个界面就会是灰/白色了, 至于闪烁的问题, 应该是由于每次刷新失败导致的问题. 这么一讲还真可以讲的通. 再仔细看一下代码吧:) 下面是一段类似于朋友ontimer函数的代码:

void CMyDlg::OnTimer(UINT nIDEvent)
{
    if (nIDEvent == MY_TIMER_EVENT)
    {
        //
        // draw the clock
        //
         CDC *pDC = GetDC();
        CDC CompatibleDC;
        CompatibleDC.CreateCompatibleDC(pDC);
        CBitmap bmp;
        bmp.LoadBitmap(IDB_DIGITS);
        BITMAP bitmap;
        bmp.GetBitmap(&bitmap);
        CompatibleDC.SelectObject(&bmp);
        //
        // draw minutes/seconds, using hte digits in the bitmap...
        //
        pDC->StretchBlt(200,565,87,135, &CompatibleDC,(bitmap.bmWidth/12) * minute,
                0, bitmap.bmWidth/12,bitmap.bmHeight,SRCCOPY);

        ReleaseDC(pDC);
    }
}

初看貌似没有什么问题, dc对象被正常释放了, 不过再仔细看一下! 注意这里的CBitmap以及selectObject, 这里是有泄漏的,或许你会说CBitmap的析构函数会释放它使用的gdi 对象, 在msdn里的LoadBitmap的方法说明里也是这么讲的:

The loaded bitmap is attached to the CBitmap object.

If the bitmap identified by lpszResourceName does not exist or if there is insufficient memory to load the bitmap, the function returns 0.

You can use the CGdiObject::DeleteObject function to delete bitmap loaded by the LoadBitmap function, or the CBitmap destructor will delete the object for you.

但是请注意下面的一行!

Caution:

Before you delete the object, make sure it is not selected into a device context.

这里提到请注意在删除一个对象之前请确认它没还没当前的设备上下文选中! 如果删除一个当前被使用的对象会有什么后果? 虽然没有找到文档, 但照猜测的话那就是删除失败! 所以毫无疑问每次都会导致一个CBitmap的gdi对象的泄漏! 所以修好这个问题应该是在使用完这个bitmap对象后再使用selectObject把选择原来的gdi 对象, 原来的gdi对象可以通过CompatibleDC.SelectObject(&bmp);的返回值得到. 所以修改后的代码应该是这样:

        CBitmap* oldObject = CompatibleDC.SelectObject(&bmp);

        //
        // draw minutes/seconds, using hte digits in the bitmap...
        //
        pDC->StretchBlt(200,565,87,135, &CompatibleDC,(bitmap.bmWidth/12) * minute,
                0, bitmap.bmWidth/12,bitmap.bmHeight,SRCCOPY);
        pDc->SelectObject (oldObject);  //select the old object.!
        ....

这样应该就可把这个问题修好啦! (没有机会测试, 但应该没有问题…).

再另外, 朋友告诉我他们找了一个人修了一下, 他们的方法是把那个CBitmap对象变成一个全局对象, 这样只要load一次, 所以也不会出现严重的泄漏情况(顶多一个gdi 对象, 另外效率相对每次都要load要好一些), 所以也可以算一个方法:)

近日一个朋友发过来一个页面, 说是上面有一段代码执行慢, 想看看能不能用一些方法让这个等待过程不要这么久, 看了一下代码, 朋友所指的代码大概像下面一段:

if (cond)

{

$query = “select id, name from demoTable where age >= “ . $age . “ and score >= “. $score . “ “;

$result = mysql_query($query);
list( $id,$name) = mysql_fetch_row($result);
print "
".$id."

";
print "
;".$name."

";

}

另外的信息是, 数据库的记录大概是三十多万条, 由于这个查询语句要在一个循环语句里执行多次, 当循环十次的时候速度会很明显的很慢.

据俺已有的知识和对mysql的理解, 对于十万量级的记录, 数据库的效率应该没有问题, 首先想到的便是从优化数据库开始, 第一条当然是建立索引了, 于是建议他用age + score做一个索引, 但朋友讲做过索引后没有太大影响(我怀疑他是单独为age 和 score做了索引, 我的意思是为age/score做一个综合索引, 但后面这个就没机会尝试了). 于是再尝试一些新的方法, 回过头去分析这段代码, 可以发现, 这里只是用到了返回结果集的第一条记录(或者原来的作者只期望得到一条记录), 毫无疑问, 把所有的记录查询下来是很破费时间/内存的, 于是从这里入手, 我们把查询改成只查一条记录.

于是修改后的查询语句就是

$query = “select id, name from demoTable where age >= “ . $age . “ and score >= “. $score . “  LIMIT 1“;

让朋友尝试新的代码, 果然速度提升了很多, 基本不用再做其他的优化了. 那我们分析一下加上LIMIT 1之后相对能优化了多少次的查询, 这里我们假设每条记录被查询到的机率相同(不然还要再具体分析就太麻烦了…)

1. 假设没有索引, 那么对于原始查询, 基本是遍历整个表, 时间复杂度为O(n), 而对于优化后的查询来讲, 它会找到第一条匹配的记录后返回, 平均时间复杂度为(1 + n) / 2, 相当于优化了一半的时间.

2. 假设分别建立了age和score的索引, 对于原始的查询, 平均时间复杂度(二分法)应该大致在log2(n) + (log2(n/2) 左右, 这个需要根据具体的查询来分析, 不过这个值应该也算差不多, 而对于优化后的查询时间复杂度大致为 log2(n) + log2(n/2) = 2 log2(n) – 1, 貌似并没有优化掉多少时间 (是不是这里错了???? )…….

至于空间复杂度, 如果对于每次查询只可能有一条记录满足条件, 则都为O(1), 如果是有可能有多匹配记录, 当然对于优化后的查询会好很多.

April 14th, 2009my shell tips

最近无聊的时候记下来的两个小tip:)

1. login的时候随即打印一个ASCII的图案。

这个比较无聊,基本原理就是把一些预先准备好的ASCII图案分别写成一个文件,在登陆的时候就是随机选取一个文件然后cat就可以啦.

Sample code:

#print out a logo to the screen...
logoDir="~/.logo"
if [ -d $logoDir ] ; then
cd $logoDir
# '*' is a filename wildcard to match all files in the current directory
set *
# Use the syntax for arithmetic expressions.  "%" is the modulo operator
# Shift arguments by a random number between 0 and the number of files
shift $(($RANDOM % $#))
echo -e '\e[0;32m'
cat "${logoDir}/$1"
echo -e "\e[0m"
fi

上面的代码就是把所有的ASCII图案放在~/.logo下面,然后再登陆的时候首先使用cd进入~/.logo目录,然后用set *来默认匹配所有文件名,
shift $(($RANDOM % $#)) 则是随即一个整数然后和文件数取模并选择对应的文件名,
echo -e '\e[0;32m' 这一句是用来是后面的字符为绿色(因为白色的图案不好看啊…)
echo -e "\e[0m" 中止前面的改变字体颜色的效果,这样就不会影响后面的打印结果。

当然, 要记得去找一些ascii 图片放到你的.logo目录里啊:)

2. 动态更新putty的窗口标题

使用putty的ssh的同学们都会想putty可以向其他的终端模拟器一样根据当前目录啥的动态更新标题栏,其实这个也可以再putty里实现,这里需要注意两点:

a. 确保没有打开putty的禁止远程改变窗口标题的选项,这个选项可以在Terminal==>Features 里找到。

putty

b. 在你的登陆脚本里export 一个名为PROMPT_COMMAND的变量,顾名思义它需要是一个命令,下面是我的配置(注意开始的和末尾的数字都是必须的):

PROMPT_COMMAND='echo -ne "\033]0;${HOSTNAME}: ${PWD} -$USER\007"';export PROMPT_COMMAND

打印的格式为:hostname: /home/pangwa/src – pangwa

重新登陆或者source一下你的初始化脚本就可以了:)

March 22nd, 2009当下

又有很久没有更新 — 不是因为生活的很空虚, 只是自己的状态不适合写出些东西让别人来看. 太过快乐和太过悲伤都不适合写些放在公共域里的东西, 一是前者怕会因为高兴过了头而写些幼稚而快乐的话儿, 二是后者写出来的东西总会太过阴暗, 如果不写清楚上下文而单单发一通牢骚又怕遭人误读.

—- 偶尔会有孩子般的快乐, 但却很难像孩子一样写下这快乐来.

前段日子一口气从网上下来Bob Dylan的25张专辑, 本打算全部听上一遍, 后来发现这项工程相当浩大, 于是作罢, 便把这许多歌儿放在播放列表里, 和其他的所有歌放在一起, 然后便就随机播放, 这样偶尔便可以听到其中一首, 感觉很淡. 今天下午有上小半天的闲暇时光, 便翻出那只部分铜线完全露在外面, 胶皮大部分基本全部脱落的森海的MX51来, 戴在耳朵上, 开始听起音乐来, 不知怎的一会儿功夫就听到了Dylan的几首歌来, 感觉很奇妙, 一个老男人用老男人的唱法在你耳边给人讲些故事/道理 — 只是原谅我吧, 我没听懂多少歌词.

日叁省乎己, 当然咱是做不到君子的境界, 只是偶尔会有少许对自我意识的反思: 做过的事情是不是做的对了? 自己的想法是不是还在正途上? 生活是不是还在正确的轨道上? (自己能意识到的)做错了的事情为什么会做错, 当时的心境又如何, 为什么会有那样的心境? 而这样, 每次的反思都会发现一个卑微而渺小的灵魂, 总是在重复着某些错误的同时改正着一些错误但又会犯下一些新的错误.  不知者不罪, 当知道自己正在做错的事情时, 只好心中一声阿弥陀佛.

“你真有毅力啊!”, 同事得知我每天会从公司走到人民广场坐地铁而不是就进坐二号线时这样对我说. 当然这不是关乎毅力的问题, 因为自己根本就没有坚持每天要做这件事情的想法, 只不过是习惯每天在路上看着重复的风景, 听着重复的歌儿, 走着重复的道路, 任由思想重复的在空中飘着.

奇妙的事情, 会发生吗? 不会发生吗? 我们当然不会每天很傻的问这个问题, 于是当它发生时, 才知道这是一个惊喜.

March 10th, 2009旅程 – 至

早上七点半左右到达武昌, 没有出现昨晚所担心的被换了假票的情况:). 由于要等一位晚来的朋友, 要在火车站仪一个半钟头左右.

先是找了家地方吃好早饭, 然后便是换上轮滑鞋, 开始适应场地, 有段日子没有好好玩轮滑了, 年后这是第二次玩, 上次就是周四的时候穿上半个小时恢复性的玩了一会. 车站的出口是在地下一层, 门口就是一大片空旷的场地, 于是就在这里玩了起来, 因为没有带桩, 并且很久没玩, 也就是随便重复着仅会的简单动作, 不大一会便出了不少汗.

等朋友来到, 便开始出发游玩,  自己没有做太多功课, 幸好朋友对武汉很熟, 在他的带领下, 先后转了, 武大, 华中师大, 东湖, 黄鹤楼, 外滩, 汉中路? 据说这些都算是比较有名的景点了, 没有太多可讲的地方, 不过中午吃饭时候点的一个什么东湖臭桂鱼是真难吃!!!

再另外, 武大和华中师大学校里山坡比较多, 轮滑比较吃力, 下坡的时候要紧踩刹车(没穿护具, 不敢下坡时太彪速度), 轮子估计磨损了不少. 黄鹤楼的门票50块, 抢钱啊, 于是我也没上去……

最后, 本来打算蹭朋友的相机, 结果他没有带. 于是没有留影.

March 9th, 2009旅程 – 启

这次的旅程的起点很奇妙, 我这样想.

从坐上火车开始.

  先是买在门号车的下铺, 刚脱了鞋, 正准备坐在床上休息, 却被对面铺的PPMM的老公央求着, 换了车, 原因是, 丈夫先是买的票, 后来因为行程原因打算和妻子一起, 于是丈夫把票改签(头一回听说火车票也可以改签的), 妻子买了一张六号车的票, 于是等上了车, 妻子发现对面铺是一个单身男青年, 便让丈夫来求我换票. 君子爱成人之美, 咱也学君子一把, 于是一路小跑, 那位丈夫帮我拿着包, 奔到了三号车厢. 放好行李, 屁股刚坐在床上,对面的一位大爷就对我讲:”小伙子, 请问你能不能做个好事, 和我老伴换一下火车厢啊, 她有点晕车, 我们这不在一个车厢, 不方便照顾, blabla…", 听完前两句我的头就突然一蒙, 心中也不由得有点警惕:怎么这么巧让我遇上两拨换票的人啊? 不会遇到换假票的吧? 为了安全起见, 只好说, 算了, 俺不换了, 太麻烦了. 那们大爷又说了几句, 反正装作没看见, 自己看起自己的书来.

  书看了一会, 但心里却越想越不是滋味:遇到换假票的机会比较小, 也就是一张票钱的事, 可是这老大爷说的要是真的话, 人家老两口分开也太不好了, 没人性啊, 这事要是等咱老了遇上, 会想别人咋办哪?? 犹豫几分钟后, 感觉不搞定这事, 晚上睡不好觉, 于是便作无奈状对他讲: 算了, 走吧, 我和你换. (瞬时感觉自己的形象高大了起来),于是再又一路小跑, 和老大爷飞奔到五号车, 找到了他的老伴, 再次安顿下来.

  这次做好事似乎还真有了好报, 对面有个貌似不错的mm正拿着psp玩的正高兴. 另外还有一个长发的女人, 只是在望着窗外, 看不清楚她的样子 — 过了好一会, 发现望着窗外的mm似乎是在抽泣 — 不知道为什么.

  于是拿出mp3来, 自己开始听歌, 一会时间过去后, 忽然听到长发的女人在讲电话, (摘下一只耳机, 偷听, 满足自己的八卦心理). 只是听她讲到:”你走吧, 你走吧!….”把这三个字重复了不下十遍, 中间抽泣声, 这样看来应该是在经历着咱们不知道的感情纠葛, 这人生.  写下这些, 火车已经开动, 而她还在对着车窗抽咽, 而那个ps mm则不见了踪影.

  另外在火车上忽然想起了friends里Chandler在大停电的那集, 发现自己很多时候也像他那样猥琐.

另外为了不显得自己过于没文化, 在睡觉前上网找了一下毛主席的词(才饮长沙水, 又食武昌鱼那个, 比较应景的), 贴出来学习一下:

水调歌头·游泳
毛泽东
一九五六年六月
才饮长沙水,又食武昌鱼。万里长江横渡,极目楚天舒。不管风吹浪打,胜似闲庭信步,今日得宽馀。子在川上曰:逝者如斯夫!
风樯动,龟蛇静,起宏图。一桥飞架南北,天堑变通途。更立西江石壁,截断巫山云雨,高峡出平湖。神女应无恙,当惊世界殊。

中铺的兄弟打呼噜!

声音很大, 但很有节奏, 开始时被下了一跳, 过一段时间之后便习惯了这规律的声音, 在疲惫中睡去.

                                                                                                                        09年3月6日晚.


© 2007 pangwa’s Blog | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress