空门 的个人资料Gateway to nowhere照片日志列表更多 工具 帮助
2009/10/31

Hacking firefox userChrome/userContent

     自从发布了 Mozilla Firefox for Windows CE 6.0 之后,总是有人要我改按钮大小,优化界面,如此这般。其实,每个人都可以自己折腾 (感谢水木上的 tgf6eta 和 sly9)。在 Profile 目录下面有个 Chrome 目录,在下面创建 userChrome.cssuserContent.css 就能很方便地改变 Firefox 的界面。例如:

PrtScn20091028214630
修订 userContent.css

    不过,Firefox 对旋转的支持并不理想,对页面尺寸的计算出现了误差:

PrtScn20091029001248 PrtScn20091028213940 

     我的时间很有限,我宁可多花点时间在 Trotsky Branding 的图标上,也不会去费力美化界面。我宁可多花些时间在 Windows CE 6.0 和 M8 SDK 的学习上。毕竟,这才是我的主要目的——Fennec/Firefox 都只是我热身的一个小插曲罢了。

Breakthrough in Project Trotsky (nullgate’s private firefox build for M8)

     It’s almost ready to be released. Here are some previews of the Trotsky branding:

PrtScn20091030193720PrtScn20091030193731

Trotsky home page (marxist.org) and about(no text changes at all, so no offending to Mozilla):

PrtScn20091030194004PrtScn20091030194041

Keyboard hacking (for password input) and Chromin frame (activated by nightly tester tool):

PrtScn20091030120210 PrtScn20091030113319

     The actual breakthrough is powered by M8’s platform APIs. The CE keyboard can be activated by acceleration sensor, while the fire-guetures can be suppressed by IR sensor. Fire-guestures is very useful for firefox CE, but it also causes a lot of problems if the trigger button is set to left (left is all what we have on M8, unless someone put an ugly LL_MOUSE hook into the system). With my hand above IR sensor, I can finally interact with the page without the inference of fire-guestures.

     A video may be released very soon.

BTW: As an internationalist, I don’t see any suitable language to announce Trotsky related stuff other than English.

2009/10/30

与 Mozilla 同步发布 Firefox 3.6 beta for Windows CE 6.0

http://cid-30f50c1bf7f56351.skydrive.live.com/browse.aspx/Firefox-wince-3.6/Namoroka/Beta/

空门不提供任何支持和保证,如果对此不满请勿下载安装
开发者可以 email 交流,非开发者请不要联系我,谢谢
请下载 firefox.js 并覆盖 default/pref 的 firefox.js
既然是纯洁版,当然不包含 preference hack 啦

About
Mozilla 尚未更新页面

      今天,Mozilla 终于要发布 Firefox 3.6 beta 了,我认为有必要同步放出 Windows CE 版本。不同于 Nvidia 定制的 Windows CE 版本,我编译的这个版本只需要 ddraw 支持。根据 Mozilla 的注释,该版本的 jemalloc 可能不能在 CE5.0 下正常工作。这并不是一个 M8 SDK 编译的版本,因此理论上应该可以在大多数 Windows CE 6.0 的设备上运行。所以,如果需要输入法,请使用 M8Key 等辅助软件;如果需要拨号,请使用待机助手等辅助软件;如果需要选择文件——请耐心点选。

     推荐插件:Fireguestures, Nightly Tester Tool, Chromin Frame

     同时提供 Firefox 3.6 b2pre,但是并不推荐使用。

     补充:由于用了平台标志 QRfpe-、QRarch6,应该只能在 ARM11(v6)系统上运行。有空编译一个不用平台优化的版本,才能在普通的 Armv4i 设备上 运行。此外,这玩意儿似乎不能再模拟器上运行(也是优化造成的)。

BTW:Trotsky 作为押轴戏,不可能这么早登台的。由于托派“不断重构”的信条,Trotsky 将不会基于 3.6 Beta Release,而是某个更新的版本。

Sunspider PrtScn20091025104432
Firefox 3.6 Beta <-------> Trotsky build 1

2009/10/27

M8 上的实时路况似乎很棘手

     虽然我也就是打车的时候参考一下,但还是觉得不爽。Google Maps 是内存杀手,就不说了(这玩意儿 wifi 能用,遇到 edge 网络差就狂吃内存):

gditu

交管局的 Flash,PocketIE 能看到地图却看不到路况:

PrtScn20091027204054

Sougo 的相对靠谱,但是刚 load 出来就刷新,至于么:

PrtScn20091027211649 PrtScn20091027212448

有谁能推荐点靠谱的么?

BTW: Firefox 十月革命纪念版预览:

PrtScn20091027232154 PrtScn20091027232234

2009/10/25

Codename: Trotsky

trocllie

     作为一个准托派,为了纪念十月革命的实际领导者,苏联红军的缔造者——Leon Trotsky,我将自己维护的 Firefox for M8 内部代号定位名 Trotsky。正巧十月革命的纪念日即将到来,我计划在这一天之前发布第一个版本,暂定名为十月革命纪念版。

W020071130407322966886 
时间会证明十月革命的意义

BTW:由于这是一个 private build,不会使用 Mozilla Firefox 提供 branding。相信会有很多人对此表示不满,并且会抵制托派倾向。但这是我的自由,想要用没有夹带私货的版本,大可以等待我公开补丁自己编译(如果等不及了,也可以写信给我要尚未完善的补丁,但是仅此而已)。

PrtScn20091025104432

PrtScn20091024234154

2009/10/24

Firefox w/jemalloc on M8SDK

      经过将近一个月的 hacking,我终于征服了 jemalloc。回头看,hacking 的捷径就是没有捷径——只有在理解相关技术的前提下,才可能解决问题。

      jemalloc 是 BSD 默认的内存分配器,其特点前文已经介绍过了。要在非 BSD 系统上使用它,就必须绕过系统默认的内存分配器。Mozilla Firefox 在 windows ce 上使用一个 shunt 包(导向器)来拦截系统定义的 malloc/free/realloc/calloc/new/delete 等函数。它包含一系列头文件和 mozce_shunt.dll,替换 coredll.dll 导出的内存管理函数。遗憾的是,他们漏掉了 _msize。由于 Mozilla 使用 CE5 Standard SDK 作为主要的开发环境(其实还有 WM SDK,但是都是 CE5),使用的是较老的 CRT,Firefox 依赖的 CRT 函数并不需要 _msize。然而,CE6 的 CRT 越来越接近桌面系统,新设计的 CRT 函数中产生了对 _msize 的依赖。由于 _msize 的存在,以及微软 Linker 的如下特性

The linker searches for unresolved externals in the following order:

  1. Find all modules in the library that define current unresolved externals.
  2. Process those modules (you may pickup more unresolved externals). The linker keeps making passes through that library until no new unresolved externals are picked up.
  3. It then advances to the next library.
In a similar manner, the linker makes a pass through the entire set of libraries. After the last library is searched, if new unresolved externals have been picked up, it returns to the first library and makes another pass.
Problems can be avoided if you do not use bidirectional cross-library references (that is, avoid library A calling something in library B that calls something else in library A). Try to make each library as self-contained as possible.

结果,当系统在找到 _msize 之后,又顺便在系统的库里面找到了 free/realloc 等函数。由于这些函数都是成套使用的,将一个 jemalloc 分配的指针送给系统 CRT 提供的 _msize、free、realloc,程序如果 crash 就算是给面子了。Firefox 不会 Crash,因此连暴力调试都没办法。

     在最初的半个月里面,我只知道用 M8 SDK 编译出来的 Firefox 一定错误的引用了系统 CRT 的某个内存函数。然而我并不知道究竟是哪些函数被导入了,以及问题出在哪些 dll 里面。我试过很多办法,包括尝试暴力调试。不幸中的万幸是,我一直没搞定调试环境,否则一定会浪费更多时间。前些天,我终于放弃了指望奇迹发生的想法,决定研究 linker。幸运的是,我找到了这篇文章提到的内容:

如果你系统中安装的有Visual C++,你可以使用DUMPBIN程序来看一看OBJ文件中的节。

于是我终于可以看到 obj、lib、dll、exe 里面的符号以及相互依赖关系了,一下子为我打开了一扇大门。但是最后我发现我根本不需要 dumpbin,因为 Mozilla Build 默认就输出了 map 文件,只需要看这个 map 文件就可以知道 dll 文件的 export 和 import:

0001:000d4f40       getenv                     100d5f40 f   mozce_shunt:mozce_shunt.dll
0001:000d4f50       free                       100d5f50 f   mozce_shunt:mozce_shunt.dll
0001:000d4f60       realloc                    100d5f60 f   mozce_shunt:mozce_shunt.dll
0001:000d4f70       malloc                     100d5f70 f   mozce_shunt:mozce_shunt.dll
0001:000d4f80       _msize                     100d5f80 f   mozce_shunt:mozce_shunt.dll
0001:000d4f90       memset                     100d5f90 f   corelibc:COREDLL.dll
0001:000d4fa0       strrchr                    100d5fa0 f   corelibc:COREDLL.dll
0001:000d4fb0       strcpy                     100d5fb0 f   corelibc:COREDLL.dll
0001:000d4fc0       memcpy                     100d5fc0 f   corelibc:COREDLL.dll
0001:000d4fd0       strlen                     100d5fd0 f   corelibc:COREDLL.dll
0001:000d4fe0       _isctype                   100d5fe0 f   corelibc:COREDLL.dll

于是,我写了十来行 perl 程序分析 map 文件,用来对比 CE5 SSDK 和 M8 SDK 链接时从 coredll 中引入函数的区别,结果我很快便发现了问题。Firefox 的若干 dll 中,本来不依赖任何内存分配函数,但是在 CE6 的 CRT 中,却产生了对 _msize 的依赖(据我推测,应该是一些安全性的改良),由于这些 dll 本来不从 mozce_shunt.dll 中导入任何函数,因此它们优先从 coredll 中导入 _msize、free 和 realloc。知道了问题,再了解了微软 Linker 的脾气,对症下药就简单多了,只需要在 mozce_shunt.def 中增加 _msize 的导出,然后到处增加这样的函数即可:

__declspec(dllexport) void __mozce_anchor_nssutil3( void )
{
       free(realloc(malloc(4), _msize((void*)0)));
}

换句话说,强迫这些 dll 优先导入 mozce_shunt.dll 中的内存操作函数,不给 coredll.dll 任何机会。

     就这样,一切问题都消失了,Firefox w/jemalloc 终于可以在 M8 上正常运行了。简单总结一下:

    1. Win32 自带的内存管理函数性能的确不如 jemalloc
    2. Mozilla 的 JS 引擎真是内存杀手,很显然,它自己不做内存压缩
    3. 要想绕开系统默认的 CRT 函数,不了解 Linker 基本上是盲人摸象

     以我愚见,Mozilla 的 JS 引擎把内存分配的问题完全抛给 jemalloc 是有些问题的。它应该向 JVM 和 CLR 学习,完全接管内存管理,尤其是需要主动进行内存压缩。在 CLR 和 JVM 中,内存管理器会不断地改变内存布局,对象地址并不是固定的。这虽然带来了额外的开销,却缓解了传统 C/C++ 程序中内存碎片的问题。

BTW:不知道 Chrome 的 V8 引擎是怎么管理内存的。我的直觉是,V8 一定是拿空间换了速度。

还是 Perl 靠得住啊!

     说来惭愧,虽然 Perl 是我第一门深入学习的语言,现在我已经完全是外行了。今天靠 Google 搜索关键语法写了几十行代码来分析 Linker 生成的 map 文件,总算找到了 M8 SDK 编译出来的 Firefox w/jemalloc 不能用的嫌疑之一了:

$ perl parse.pl js/src/js3250.map
parsing /e/Temp/october/js/src/js3250.map
parsing /e/Temp/ce5+jemalloc/js/src/js3250.map
+coredll:COREDLL.dll    TerminateProcess
+corelibc:pegdmain.obj  _DllMainCRTStartupHelper
+corelibc:COREDLL.dll   _XcptFilter
+coredll:COREDLL.dll    __imp_TerminateProcess
+corelibc:COREDLL.dll   __imp__XcptFilter
+corelibc:COREDLL.dll   __imp___security_gen_cookie2
+corelibc:COREDLL.dll   __imp__msize
+corelibc:COREDLL.dll   __imp_memmove_s
+corelibc:seccinit.obj  __security_cookie
+corelibc:seccinit.obj  __security_cookie_complement
+corelibc:COREDLL.dll   __security_gen_cookie2
+corelibc:seccinit.obj  __security_init_cookie
+corelibc:cexit.obj     _exitflag
+corelibc:crt0dat.obj   _initterm
+corelibc:COREDLL.dll   _msize

-coredll:COREDLL.dll    LocalAlloc
-coredll:COREDLL.dll    LocalFree
-coredll:COREDLL.dll    LocalReAlloc
-coredll:COREDLL.dll    LocalSize
-coredll:COREDLL.dll    RaiseException
-coredll:COREDLL.dll    __imp_LocalAlloc
-coredll:COREDLL.dll    __imp_LocalFree
-coredll:COREDLL.dll    __imp_LocalReAlloc
-coredll:COREDLL.dll    __imp_LocalSize
-coredll:COREDLL.dll    __imp_RaiseException
-libcmt:invarginternal.obj      _invalid_parameter
-libcmt:invarg.obj      _invoke_watson

     CE5 SSDK 编译出来的版本可没有这个 _msize。WINCE 的 shunt 文件花了很大的力气来屏蔽系统自带的 malloc/free/strdup 等一列函数,却漏掉了这玩意儿。

image

    Perl 真是 hacking 必备的工具呀,算上学习的时间,写这些脚本花的时间也不到一小时。

补充,漏洞还真不少:

$ perl parse.pl nsprpub/lib/ds/plds4.map
parsing /e/Temp/october/nsprpub/lib/ds/plds4.map
parsing /e/Temp/ce5+jemalloc/nsprpub/lib/ds/plds4.map
+coredll:COREDLL.dll    TerminateProcess
+corelibc:pegdmain.obj  _DllMainCRTStartupHelper
+corelibc:COREDLL.dll   _XcptFilter
+corelibc:COREDLL.dll   __C_specific_handler
+coredll:COREDLL.dll    __imp_TerminateProcess
+corelibc:COREDLL.dll   __imp__XcptFilter
+corelibc:COREDLL.dll   __imp___C_specific_handler
+corelibc:COREDLL.dll   __imp___security_gen_cookie2
+corelibc:COREDLL.dll   __imp_free
+corelibc:seccinit.obj  __security_cookie
+corelibc:seccinit.obj  __security_cookie_complement
+corelibc:COREDLL.dll   __security_gen_cookie2
+corelibc:seccinit.obj  __security_init_cookie
+corelibc:cexit.obj     _exitflag
+corelibc:crt0dat.obj   _initterm
+corelibc:COREDLL.dll   free

-coredll:COREDLL.dll    LocalFree
-coredll:COREDLL.dll    __imp_LocalFree

2009/10/22

难以跨越的数字鸿沟

      Firefox 的 Window CE 版本是 NVidia 为了推广自己的 Tegra 而资助 Mozilla 开发的。正因为这样,Firefox 的 Windows CE 渲染后端得到了改善,Cairo-ddraw-surface 的版权页也烙下了 NVidia 的印记。NVidia 为了进一步提高其图形性能,还应用了 OpenGL ES 2.0 来对 ddraw-surface 进行加速。但是,它依赖 OES_EGL_image extension,这也是 NVidia 提出的 extension,如果牺牲性能,理论上还是能绕过去的。最要命的是,它所用的 Shader 依赖 NVidia 的扩展,几乎不可能在别的平台编译通过。这使得在其他的移动平台上使用硬件加速 Firefox 变得几乎不可能——除非完全重写这个渲染管线。

     随着技术的发展,这样的数字鸿沟反而变得越来越难以逾越了。

BTW:我并不是想谴责 NVidia,商业公司为了推广自己的硬件而提供非通用的软件无可厚非,更何况 NVidia 还贡献了很多扩展并向开元社区捐献了代码。虽然没有硬件加速,所有的 Windows CE 版本 Firefox/Fenenc 都能受益于 ddraw 版本的 Cairo。

2009/10/17

Firefox 与 FlashLite

      前几天看到有人从 Windows CE6.0 R3 中提取了 FlashLite,可以在 PIE 中正确浏览 Flash。恰好我切换到 Namoroka,而 Mozilla 为 Nvidia 制作的 CE 版本正好有 flash 支持。但是我很快就遇到了问题:在 M8SDK 下面完全无法编译,有很多在 sal.h 中定义符号都找不到。这让我非常困惑,不过用 CE5 SDDK 可以正常编译,于是我得到了一个支持 Flash 的版本:

flash flash2

     虽然我个人认为,Firefox 的 Flash 插件完全没有价值。首先它有很多 FlashLite 3.1 支持的 Flash 无法打开;其次它会浪费大量内存,拖慢页面相应速度;最后,z-order 有问题,经常会挡住滚动条,显示出来的全都是垃圾广告。如果真要看 Flash 内容为主的广告,完全可以用 PIE (这个页面 Firefox 就无法争产显示):

PrtScn20091017001751

     不过本着一个工程师的好奇心,我研究了一下 M8SDK 无法编译的问题,结果发现 M8SDK 中提供了一个完全不同版本的的 sal.h,导致依赖 VS2008 自带版本的 sal.h 丢失:

image 

     对此我很困惑,难道 M8SDK 的开发人员就没考虑过兼容性问题么?M8SDK 中这些小写版本有可能是 CE6 提供的新定义,很可能是为了避免和老定义冲突提供的。但是考虑到 M8SDK 中有删除 time.h 里面函数定义的前科,这个问题很可能是 M8SDK 的开发人员造成的。这些宏是 atlbase.h 所依赖的,这使得 M8 的开发人员完全不能使用 Visual Studio 2008 提供的 atl 进行开发。它也正是用 M8SDK 无法编译支持 ActiveX 的 firefox 的罪魁祸首。

补充:经过仔细阅读,Meizu 使用的是过时的定义(deprecated delcarations)。首字母大写的版本是微软提供的新版本呢,微软的新版 sal.h 同时提供了兼容这些小写定义的版本。毕竟微软是一家保守的企业,没有什么比兼容性更重要的了。经过简单的 hack,M8SDK 已经能编译支持 Flash 的版本了,但是仍然有一些 bug(似乎是字符串定义不同)。

补充:经过分析,其实问题是 Mozilla Build 造成的。Mozilla Build 错误地把 SDK include 放在 VC include 前面,因此总是使用旧的定义——以及旧的 C++ libary。Mozilla Build 还强制把 _WIN32_WCE 定义为 0x502,而 M8SDK 应该使用 0x600。

还是得解决 M8SDK 的 jemalloc 问题

     换到 Namoroka(Firefox 3.6) 分支之后,jemalloc 对性能的影响变成决定性的了。Sunspider 的成绩提升是次要的,但是在运行 Sunspider 的过程中,M8 的剩余内存几乎总在 50M 之上,跑完以后用任务管理器观察,firefox “只”占用了 32M。作为对比,没有 jemalloc 的版本内存在 20M ~ 40M 之间起伏,最低的时候内存不足 20M。

PrtScn20091016230040 
相信来点 PGO 或 GC Tuning 一定能进 50s,但又能如何呢?

     Namoroka w/jemalloc 已经非常接近可用版本了,我已经成功地加载并使用了桌面版的谷歌地图(ditu.google.cn),仍有很多内存可用(这时候 CPU 已经不堪重负了,页面响应速度奇低)。为了挑战极限,我运行了 Futuremark 的 Peacekeeper,Namoroka 居然完成这一针对桌面浏览器的变态测试——虽然得分只是零蛋(Agent 显示是错误的,因为我用了错误的配置文件)。

PrtScn20091016233523 PrtScn20091017011801

     真是折腾啊,又回到了原点,我又得 hack M8SDK 了。

2009/10/15

VFP and nanojit

     Meizu M8 采用了三星的 S3C6410 解决方案,CPU 是一款 ARMv6 架构的处理器。虽然它的编号是 ARM1176,但是处理器特性和最流行的 ARM1136 完全一样,都支持浮点数协处理器(Vector Floating Point Unit)。在没有协处理器支持的情况,只能用软件进行浮点计算,开销比较大。

Vector Floating Point (VFP) coprocessor support is an architecture option. The VFP architecture supports single and double precision floating point arithmetic, and is fully IEEE 754 compliant with suitable software library support. The VFP architecture also includes a fully deterministic ‘Run fast Mode’.
Provision of a hardware floating point is essential for many applications, and can be used as part of a System on Chip (SoC) design flow using technical computing tools (eg MatLab® and MATRIXx®) to directly model the system and derive the application code. The vector processing capability of the ARM VFP can be used to increase performance of imaging applications such as scaling, 2D and 3D transforms, font generation, and digital filters.
ARM currently has VFP support for the ARM9™, ARM10™ and ARM11™ processor families: VFP9-S™ and VFP10™. Additional VFP options, VFPv3, were introduced with the ARMv7 architecture.

     由于 VFP 提供了一组特殊的指令集,通常需要编译器支持或使用汇编才能使用。不过,ARM 能对 Windows Embedded CE提供提供了良好的支持,可以在 OS 层面支持 VFP。根据 ARM 的说法,用 Visual Studio 2008 和 ARM 提供的工具编译出来的 OS 能够在 CRT 中提供 VFP 的支持;在不需要特殊编译器的情况下,普通的应用程序也可以使用硬件加速浮点数运算。

Vector Floating Point (VFP) Support for Windows Embedded CE

The Visual Studio 2008 suite of tools, used to create applications for Windows Embedded CE, includes a fully enabled VFP compiler for ARM.    This enables in-lining of VFP code for optimal performance.  Use of the VFP unit requires either disabling of the VFP exceptions or inclusion of the proper OAL code to handle such exceptions.   Details are included in the Visual Studio 2008 compiler documentation. 

ARM has and will continue to support a VFP C Library for Windows Embedded CE 6, but recommends the use of the Visual Studio 2008 suite as the preferred method of exploiting VFP hardware.  The library offered by ARM replaces software emulated floating point routines with hardware accelerated implementations.  The VFP library plugs into the Microsoft Platform Builder IDE to work with the Microsoft embedded tool chain. 

     那么,Meizu M8 的 MMobile 系统是否使用了 VFP C Libary 呢?在网上搜集到的说法是:Meizu 还没有使用 VFP,但是可能在将来的版本中提供 VFP 支持。为了确认这一点,我拿 Mozilla Firefox 做了点实验。首先,要在编译器参数中提供合适的参数:

/QRfpe- Enable Hardware Floating Point Targeting

9/7/2007

This option, when used, specifies that the compiler generates code that targets the vector floating point (VFP) on ARM family processors. If you are developing an application targeting an operating system (OS) that utilizes VFP, you might need to specify that the OS must either be in RunFast mode or support instruction bouncing.

     这是一个好消息,因为在支持 VFP 的 WINCE 操作系统上,使用这个参数编译反而会有麻烦。在 Mozilla Build 系统中,增加 QR 参数的方法如下:

export CFLAGS="-QRarch6 -QRfpe-"
export CXXFLAGS="-QRarch6 -QRfpe-"
export ASFLAGS="-cpu ARM1136"

     Mozilla 官方的 wiki 上有的地方是 mk_add_options 而不是 export,这是错误的或过时的,至少在雷区里面需要用 export。使用这些参数进行构建时,编译时间会明显变长(在我的机器上,由两小时变为三小时),同时生成的目标代码也会变大。新的代码在 Meizu M8 上运行一切正常,速度也有所提升(但应该是 –QRarch6 造成的)。于是从网上找了一个 JavaScript 的浮点数测试程序,结果让我大失所望:

PrtScn20091015142450 PrtScn20091015142859
有 VFP <------> 无 VFP

    性能提升不到 10%,难道是我搞错了?或者是测试程序不够典型?还是 Meizu MMoble 已经使用了 VFP?

  function qset(xx, yy, u, v) {
      var n
      var t, xsqr, ysqr
      var lim = 100
      var x = xx
      var y = yy

      xsqr = x*x
      ysqr = y*y
      for (n=0; (n < lim) && (xsqr+ysqr < 4.0); n++) {
        t = xsqr - ysqr + u
        y = 2.0*x*y + v
        x = t
        xsqr = t*t
        ysqr = y*y
      }
      return(n)
  }

  function mb100() {
      var dots = 0;
      var res = 100;
      var a1 = -2.50;
      var b1 = -1.75;
      var s  =  3.50;   /* side */
      var x = 0;
      var y = 0;
      var g  = s/res;   /* gap  */
      var i,j,a,b,k;

      for (j=0,b=b1; j<res; b+=g,j++) {
        for (i=0,a=a1; i<res; a+=g,i++) {
          k = qset(x,y,a,b);
          if (k > 90) dots++;
        }
      }
      return(dots);
  }

     然而 mb100() 的源代码很简单,没有太多的函数调用,全都是浮点计算,也没有频繁的内存操作。为何 vfp 没有发挥任何作用呢?我首先想到的就是 JIT (Just-in-time)。JIT 编译是一个存在已久的技术,可以将字节码和解释程序即时编译成本地代码,Java 和 CLR 都使用 JIT 提高运行速度。JIT 最大的优势在与可以在运行时充分利用 CPU 的硬件资源,而不是在编译时确定。如今的移动版 Firefox 早已支持 nanojit ,这得感谢 Vladimir Vukićević(也是他为我指点迷津才完成移植)。很显然,我的程序受到了 nanojit 的祝福,虽然 Firefox 的运行时不能得益于 VFP,但是 nanojit 编译成的本地代码却包含 VFP 指令(以及完整的 ARMv6 指令)。毕竟,Firefox 和网页中的程序都是 JavaScript(除去 Gecko,Firefox 主要由 XUL 和 JavaScript 描述)。

image

     Windows CE 环境下, nanojit 将会通过汇编代码检测 VFP 指令集。至于 Windows Mobile 为何不支持 VFP,我百思不得其解,莫非是因为 WM 中广泛应用支持 VFP 的 OS Image?总之,接下来的事情很简单,只需确保这个函数返回 false,就能在 nanojit 中关闭对 VFP 的支持。

PrtScn20091015150133 
强制关闭一切 VFP 支持

     这下一切真像大白了:VFP 至少能带来 4 倍的浮点性能提升,目前 Meizu MMobile 没有提供 VFP 支持。其实,除了 3D 游戏,手机上对浮点运算的需求是很少的。由于WebGL 的普及还遥遥无期,VFP 对移动版 Firefox 带来的影响是非常有限的。我只是本着一个工程师的好奇才拿 Firefox 作了这么一个实验,希望对其他的移动开发者带来帮助。

     如果对 nanojit 和相关的技术感兴趣,可以去了解一下 TraceMonkey

     最后,按照惯例,把可悲的 Internet Explorer 8 和 Opera Mobile 拖出来游街:

imagePrtScn20091016125321
IE8 on 2710p  <-----> Opera Mobile on M8

BTW:雷区是在太危险了,新编译出来版本性能是高了,却跑不完 Sunspider 了。这不,我打算去马达加斯加缓一缓。

PrtScn20091015231526 
比 CE5 w/jemalloc 版本还快了,优化一下应该能进 50s

2009/10/13

Firefox on M8

     说穿了,Firefox 也只是 XULRunner 的一层皮。不同于 Fennec 的是,Firefox 是 XULRunner 的默认行头。我本以为 Firefox 会占用更多的资源,但是当我从 Fennec 中偷来一些配置之后,发现它比 Fennec 更节省资源。其实也很容易理解,Fennec 需要对页面进行缩放,需要更多的 Frame Buffer,开销自然更大。如果 M8 能有个电容屏幕专用的触笔,这个 Firefox 就完美了。另外,由于我使用 trunk repository 的最新版本,编译出来的是 Firefox 3.7a1pre,基本上没有兼容的插件,强行安装 Grap and Drag 以后无法拖拽页面。虽然难用了点,但是这个版本相当稳定,我可以流畅地访问 Google Reader,或者是在水木社区灌水。今晚打算编译一个 Firefox 3.5.4,稍加完善以后就可以发布了。至于 Fennec ——还是等等再说吧!

     编译配置:M8SDK + M8Hack for fennec + Visual Studio 2008 SP1 + Mozilla Build 1.4 / Vista Business OEM on 2710p

BTW:请不奢望 Flash 插件,只有 M8 升级到 CE6.0 R3 并且集成 Flash 以后,才可能通过 ActiveX patch 支持 Flash。只怕到时候内存就更不够用了。

 PrtScn20091013101006

 PrtScn20091013102852

 PrtScn20091013103242

PrtScn20091013103606

PrtScn20091013165519

 PrtScn20091013170209

Jemalloc ain’t no silver bullet

Il n'est pas de sauveurs suprêmes: Ni Dieu, ni César, ni tribun, Producteurs, sauvons-nous nous-mêmes!

L'Internationale

警告:这是雷区(3.7a1pre)的实验结果,在 Namoroka 版本(3.6b2pre)中启用 jemalloc 有质的改善!

    可能是因为 Fennec 1.0 alpha 3 实在是太差,我对 jemalloc 报有很高的期望。整个国庆我都在试图编译一个能在 M8 上运行的 Fennec + jemalloc 版本。然而,当我最终做到这一点的时候,我发现它仅仅是一个好一点的内存分配器,而不是什么大力丸。Jemalloc 最大的优点在于能良好地支持多线程,在多处理器的情况下保持很好的性能,同时它能较好地降低反复获取和释放内存时的开销。显然,在手持设备上,只有最后一点是有意义的;而在 Windows CE 6.0 上,虚拟地址空间的碎片并不是什么太大的问题,毕竟每个进程有 1G 空间可供挥霍。降低虚拟地址空间的碎片有利于提高性能,但是对于 M8 这样主要受限于物理内存的设备,这样改善意义实在不大。是的,jemalloc 提高了 Fennec 的性能:

PrtScn20091012234826 
Fennec 1.0 alpha 4/CE5.0 SSDK + jemalloc

PrtScn20091013000753
Fennec 1.0 alpha 4/M8SDK 0.9.26 - jemalloc + patch

然而,这仅仅是 5% 的性能提升。即便是之前没有任何内存优化的 Fennec 1.0 alpha 3/M8SDK -jemalloc 编译版本,速度也比 N810 (> 100s)强很多。

     而且这部分性能变化还和我的 patch 相关:我将 SpiderMonkey 中的 VirtualAlloc 参数从 MEM_COMMIT 改成了 MEM_AUTO_COMMIT。这将节省一些物理内存,但是在访问内存时将会有额外的开销。就目前而言,我并没有发现这两个版本在物理内存的消耗上有本质的差异,倒是在启动阶段时,后者占用的内存明显要少一些。

PrtScn20091013002116
Fennec 1.0 alpha 4/CE5.0 SSDK + jemalloc

PrtScn20091013001517
Fennec 1.0 alpha 4/M8SDK 0.9.26- jemalloc + patch

在访问 www.meizu.com,仍然是后者占用的内存较少。这也符合 jemalloc 的特性:在开始阶段说,它并不节约内存,在长时间运行之后,也许才能体现其优势。不过以 Fennec 1.0 alpha 4 现在的性能,我暂时不奢求“长时间运行”。

BTW:这个版本的 Fennec 消耗的内存比上一个版本还多,但修改了 preference/mobile.js 中的默认配置以后,内存消耗顿时少了一半左右。

image 
两个版本的 mozconfig diff

image
桌面版本 Firefox 最新版本的 Sunspider 成绩

PrtScn20091012231226 
默认配置跑不过 SunSpider,必须强化 GC 倾向

警告:这是雷区(3.7a1pre)的实验结果,在 Namoroka 版本(3.6b2pre)中启用 jemalloc 有质的改善!

2009/10/12

工程师的楷模

     李强(1905-)原名曾培源。江苏常熟人。曾在杭州读中学。1922年底因反对旧礼教作文被开除。1923年到上海入南洋路矿学校附属中学。1923年秋中学毕业,入东华大学攻读土木工程专业。1925年参加上海五卅运动,被选为上海学生联合会执行委员,并任军事委员会委员,6月加入中国共产主义青年团。8月转为中国共产党党员,同时任共青团上海曹家渡部委书记。1926年任共青团浦东区部委书记,共青团吴淞区部委书记。同年秋被中共上海区委调走制造炸药,为发动上海武装起义做准备。其间从9月起回常熟开展工作,建立中共常熟特别支部,推动筹建国民党县党部。1927年春任常熟县临时行政委员会委员。四一二反革命政变后,转去武汉到中共中央军事部做机要工作。大革命失败后,转至上海,仍在中央机关工作。1928年根据中共中央领导指示,系统自学了美国大学的无线电专业课程,秘密研究制造了中共的第一批无线电台,任电台台长。1929年参与组织主办中共中央无线电人员训练班,任教员,培养了中共第一批无线电技术人才。同时组建中共中央特科第四科任科长,负责党内无线电通讯,并从事保卫和情报工作。1931年秋被中共组织派到莫斯科,入苏联政府邮电人民委员会电信科学研究所任工程师。1935年任该所研究员。他用菱形天线理论进行演算,得出演算方法和公式,撰写成《菱形天线发射》等论文。抗日战争爆发后回国到延安,任中共中央军委军事工业局副局长、局长。1942年后改任延安自然科学院院长。参与领导组织陕甘宁边区和敌后抗日根据地的军火研制工作,被评为陕甘宁边区特等劳动模范。解放战争时期,1947年底担任建造中央人民广播电台的领导工作,克服困难,艰苦奋斗,终于完成任务,为人民的广播事业的创建做出了贡献。1948年8月被选为中华全国总工会执行委员。中华人民共和国成立后,历任中央人民政府广播事业局局长,电信总局局长,无线电总局局长,中华人民共和国驻苏联大使馆商务参赞,对外贸易部副部长。1973年11月任对外贸易部部长。1981年9月任国务院顾问等职。是中国科学院学部委员,中国电子学会名誉理事,中国兵工学会名誉顾问,第三、四,五届全国人大代表,中共第九、十、十一届中央委员,中共十二大上被选为中央顾问委员会委员。1978年获国际水星奖执行委员会授予的1978年个人国际水星奖。

2009/10/11

Fennec + JeMalloc 终于调通了

The secret ingredient of my Secret Ingredient Soup.
Come here. The secret ingredient is...
...nothing.
You heard me. Nothing!
There is no secret ingredient!
Wait, wait. It's just plain old noodle soup?
You don't add some kind of special sauce or something?
Don't have to. To make something special, you just believe it's special.
There is no secret ingredient.

Kungfu Panda

    秘诀就是:不要用任何技巧。
    在与 Mozilla 的 Vladimir Vukicevic 通信后,我安装了 Windows CE 5.0 Standard SDK。使用它而不是 M8SDK 编译,以前辛辛苦苦写出来的补丁一个都不需要了。只需要把 M8SDK 中的 ddraw.h/ddraw.lib/cellcore.lib 拷贝到 CE 5.0 SSDK 的对应目录,就能顺利地编译 Fennec (至少 2009/9/12 取下那那份代码如此)。现在只剩下一个问题:由于使用了 SSDK,它不支持软键盘(SIP)。

    遗憾的是,使用了 jemalloc 的 fennec 虽然稳定了很多,但是仍然很慢,并且吞噬大量内存。这让我比较困惑,CE6 毕竟能为 Fennec 提供接近 70M 的物理内存;在那些 CE5 内核的 WM 手机上,32M 的虚拟地址空间限制又如何能满足 Fennec 的胃口呢?

PrtScn20091011224130

PrtScn20091011223710

PrtScn20091011224052

2009/10/8

Mozilla’s Jemalloc Patch available for Visual Studio 2008

     在 Ayakawa 提供非正式的 Jemalloc patch 之后,Mozilla 终于正式支持 Visual Studio 2008 了。其实早在我成功编译 Fennec 之前,Mozilla 的代码库中就已经有 Jemalloc patch 。不过受限于网络,我没回家之前没敢更新。今天我本来只是想更新到最新的代码,顺便完善我的 M8 Patch,结果撞了大运。刚发现 WINCE 分支强制要求 MOZ_MEMORY 选项的时候,我颇有些郁闷(我手头没有 Visual Studio 2005),幸好我做了些调查:

image

     于是,我在地铁和出租车上开始了编译(这也是平板电脑 + SSD 的优势):

image

     遗憾的是,目前这个 patch 只能生成有效的 win32 代码,尚不能构建 M8 上可正确运行的版本。

BTW:我仔细阅读了 configure.in,发现 jemalloc 的版本依赖只针对 Win32 build,对 WinCE 完全无影响。看来不是编译器的问题,而是 xulrunner w/jemalloc 存在对 Windows CE 6.0 的兼容性问题。

2009/10/4

扒 Fennec 的皮

     Mozilla Fennec 其实只是 XULRunner 移动版本的一层皮而已;Fennec.exe 只是 xulrunner-stub.exe 的一张马甲而已。Mozilla Fennec 的主要功能都是用 XUL + js 来实现的,只有很少的平台相关特性由 XPCOM 组件实现。移植 Mozilla Fennec,其实主要是移植 XULRunner,因此在开发和调试的过程中,完全没必要和 Fennec 打交道。因此,Mozilla 的开发人员提供一个极简的 Mini Browser 用于测试。

     好消息是,这个测试的浏览器启动速度很快,占用内存少,Acid3 得分更高。坏消息是,它很不友好,不支持缩放,缺乏必要的优化和错误处理,它将不断地吞噬内存直至崩溃。

PrtScn20091003142226

  PrtScn20091003202809

 PrtScn20091003202818

 PrtScn20091003150812

PrtScn20091003201916

 PrtScn20091003190848

     Fennec 的得分略低,并且与屏幕布局有关系。

 PrtScn20091003161359

PrtScn20091003161524

2009/10/2

Mozilla Fennec 的救命稻草

    以下引用来自 http://blog.mozilla.com/blassey/2009/03/23/memory-dragon-slain/

It all comes down to memory.

Simply put, we were running out of memory. The frustrating part though, was that we weren’t running out of real memory. We were being constrained by an artificial limit of 32Mb (including the binary) that Windows CE places on each process. That is why otherwise extremely capable phones like the HTC Touch Pro with 288Mb of RAM were showing a beautiful checkerboard pattern. I’m still not entirely sure why this didn’t show up on our development devices before the release. I suspect it has something to do with the fact that we’re using unlocked HTC Touch Pros for development, while most of the testers seeing the problem were using handsets from Sprint, Verzion or AT&T.

Digging further, the reason people saw a checkerboard pattern, but otherwise usable UI is due in part to the way Fennec works. In Fennec, the user actually interacts with an html canvas element. We render the page off screen and then paint the image onto the canvas. In this particular case, it seems as though we were successfully rendering pages but failing to allocate enough memory to do the final paint onto Fennec’s canvas. We were handling this low memory “gracefully” and continuing to run.

jemalloc to the rescue

At first Doug Turner took a crack at cooling down this memory hot spot by improving on how we allocate memory during paints. Essentially, allocating a single buffer and reusing it every time he needed a surface to write to. This didn’t actually decrease the amount of memory we were using, but instead significantly reduced the amount of memory “thrashing,” (repeatedly allocating and freeing chunks of memory).

With that change we were able to run for much longer without running into memory problems, but it became clear that there are plenty of other places in our code that we thrash.

The solution was to use jemalloc, originally written by Jason Evans. Stuart and Vlad used jemalloc to greatly improve the memory performance of Firefox over a year ago, so it was already in the Mozilla bag of tricks.

    简单的说,只要 jemalloc 就能缓解 Fennec 对内存的需求。遗憾的是,jemalloc 和 VS2008 不兼容。我没有时间也没有金钱再去 Company Store 买一份 VS2005。

Sun Spider 成绩参考

sunspider-benchmarking-tests-2009-06-22

     Mozilla Fennec 和 Safari Mobile 还是有差距的,不过也算不错了。毕竟这是一个 webkit 提供的 benchmark。唯一能找到的 Fennec WM6 的测试结果是 87s。

Mozilla Fennec for M8 资源共享

      移植笔记、修订过的源代码、最新的两个构建版本、截图都已经上传。需要者请到我的 Skydrive 的 Mozilla Fennec for M8 目录自取。

BTW: Fennec 离产品化还有一段距离,请不要有太高的期望。