碗莲

种的碗莲冒出了不一样的芽,这难道是传说中的立叶?@@
调戏了一只鹦鹉
嘴馋,去DQ买了冰淇淋。一路吃一路走。
接近吃完,听见一阵吱吱呀呀的声音。声音传来的方向是一只刚从站立的横栏上失足滑落,头下脚上的鹦鹉,一边吱哇乱叫着,一边努力回到原先的位置。看着它努力的也挺不容易的,看看冰淇淋也没剩多少了。干脆牺牲了勺子喂它点:
一开始这鸟还很困扰的观摩一下,小心翼翼的伸出小黑舌头舔舔。估计是冻着了,立刻收回舌头转头~ 然后估计是回味过来了,再次伸头小心的舔舔~ 如是再三再四……终于下了狠心,开始毫不畏惧的连舔带啃。 我假装拿开,它还大不乐意的一边吱哇一边追着啃。萌翻了~
不过不知道会不会拉肚子啊。。阿弥陀佛~ 不是自己养的东西,也就顾忌少,也就快乐多。
升级
再一次的升级了电脑。
最近慢慢感觉到在买配件方面,不再像以前那么背了:每次刚买完,价格立刻跳水。 相反,去年刚买了硬盘,硬盘就涨了; 这刚买了8G的内存,内存就涨了;这手头64G的M4,不知道会不会延续这个传统。一切似乎都是公平的,买东西不背,别的就会相应的背起来。
taobao买了一块X2 450,换下了原来的X2 3000+,因此可以用DDR3了,于是加了8G的内存。周末,没经住诱惑,买了M4。最近花钱稍微有点猛烈了……一共干掉1k多。
M4分了两个区,分别装了2008 R2和Fedora 16 x64。感觉上似乎是快了那么一点的样子~ 至少编译mplayer快了不少。希望这个投入的产出能让人稍微欣慰一点。
Android基于distcc的分布式编译及负载均衡的实现
本文随时会根据情况进行修改,请引用的同学注意
distcc简介
distcc
distcc源起于著名开源项目samba,是一款有着较长历史的跨平台开源分布式编译解决方案。
对于大多数c语言及其衍生语言来说,编译过程主要分为三个步骤:
- 预编译
- 编译
- 链接
distcc的作用就是将第二步的编译(3.0版本后通过pump支持部分第一步)过程采用网格计算的模式,将编译任务分配至其它主机,并在编译结束后回传,以供第三步链接使用。并由此降低了发起编译的机器的负载,并提升了编译效率。
distcc本身事实上并不参与任何编译过程,而只是一个编译器(gcc等)的前端。为编译器加入分布式特性,并参与部分管理和简单的负载均衡的功能。根据官方说法,其性能提升的极限阈值是3倍速度,即根据编译池的扩大,无限接近但无法达到原始编译速度的三分之一。
截至目前为止,distcc仅支持c语言及其衍生的c++,Objective-c等的编译。无法支持Java的分布式编译。
pump
自distcc版本3.0开始,加入了基于python的新工具pump。其功能是将头文件也随同源码一起发送至编译服务器。将部分预编译工作也进行分布式处理。从而进一步的提升了编译效率。官方给出的数字是对于文件传输、编译过程有10倍的效率提升。
但pump模式的局限之处在于:在整个编译过程中,源代码(尤其是头文件)不能进行改动,否则会造成错误的编译结果。
ccache
ccache同样产生于samba项目,其作用是将编译过程中的中间文件根据预编译结果,通过hash表索引进行缓存。Ccache具有以下特性:
- 在命中/缺失上是静态的
- 自动的缓存大小管理
- 可以缓存产生的编译警告
- 容易安装
- 很低的开销
- 可以使用硬联接来避免复制与distcc不同,ccache是android官方直接支持的编译加速方案。
dmucs
dmucs是为distcc服务的分布式负载均衡解决方案。原始的distcc仅根据服务器指定的顺序来分配编译任务,无法根据编译池中服务器的负载情况进行动态的编译任务分配。而dmucs则会将编译池中主机的负载情况通知到dmucs服务主机。并由其根据负载及编译机承担能力,动态的对编译任务进行分配。
基准测试结果及分析
构建结果分析
图1展示了不同编译条件下的编译时间。其中,单机的编译参数使用了-j8, 而双机、三机的编译参数则分别为: -j12,-j15
由此图,大致可以总结出以下结论:
- distcc对android系统编译起到显著的加速作用,编译时间随着编译池中编译机器数目的增加而基本呈线性下降趋势。因为暂时无法获得更多的主机进行测试。故无法获知边界情况。
- 分布式编译的效果在android 4.0的编译过程中体现相对于 2.3更为明显。
- pump工具在编译过程中起到的速度提升作用并不明显。估计是因为android的预编译过程牵涉了大量的头文件和依赖关系,分布式得到的速度提升被文件传输过程所抵消。
- ccache的加入极大的改善了编译时间。对ccache的使用命中率,针对2.3.7平台,统计结果如下:
cache hit 878 cache miss 11494 called for link 691 not a C/C++ file 307 unsupported compiler option 48 files in cache 22988 cache size 1.0 Gbytes max cache size 20.0 Gbytes
ccache 初次编译 2.3.7 统计结果
cache hit 12127 cache miss 16 called for link 691 not a C/C++ file 307 unsupported compiler option 48 files in cache 23020 cache size 1.0 Gbytes max cache size 20.0 Gbytes
ccache 二次编译 2.3.7 统计结果
由此可见,在第二次编译时(代码未改动),cache的命中率超过了90%。而速度也因此得到大幅度的提升,基本接近初始速度的三倍。对android 4.0版本的速度提升尤为显著。但此数据对平时开发过程中代码有变化的情况仅能起到参考作用。 - 在测试过程中,dmucs的加入并未在时间上有效的缩短单编译请求的时间。原因是因为java/c的混合编译,无法根据distcc的推荐方法增加编译job的数量,也就无法充分体现分布式编译均衡的优势。但根据编译时观察,dmucs确实能有效的控制编译池中编译机器的负载,并根据编译能力进行平均分配。
- 此外,在图表中未能体现的一个结果为:发起编译的客户机平均负载在采用了分布式编译之后,在c类语言编译阶段,均有较为可观的降低。
图2展示了在三机分布式条件下编译android 4.0代码,job数目与编译时间的大致关系。

由此可知,单纯增加job数目并不能获取更好的编译时间。具体原因如下述。
存在的问题及后续解决方案的方向
由于android系统的编译过程中同时存在java的编译和c的编译,而distcc又仅支持c类语言的分布式编译。故对于android的分布式编译获得的效果不如普通纯c类语言项目明显。随着jobs数目的增加,仅能在本机处理的java编译过程反而由于机器硬件机能的限制而拖慢了整体的编译速度,甚至抵消了由distcc分布式编译获取的益处。
为了解决这个问题,可从以下几个方面入手,进行进一步的改造:
- 分割c类语言的编译过程:将整体android编译过程划分为c语言为主和java为主的两个过程,其中c语言的编译过程采用distcc编译,而java语言的编译则因循原来的编译方式。 此方法涉及android编译脚本的修改,实现较为简单。
- 修改make的实现,根据调用java/c编译器的不同,动态的调整作业数目。此改动可能涉及编译脚本修改甚至make源代码修改,实现稍微复杂。
- 将java编译过程同样进行分布式处理。可能的方式是在不同的主机上对不同的java项目进行编译。但需要物理的共享存储以及编译脚本修改。实现更为复杂。但仍在可行的范围内。
分布式负载均衡编译环境部署i
为支持分布式编译,单一编译主机需要进行以下部署步骤:
- 安装支持包: 编译主机需要安装distcc、distcc-pump、dmucs包
1
apt-get install distcc distcc-pump dumcs
- 部署交叉编译工具链至特定位置:
将android源码自带的prebuilt目录复制到固定地点,比如:/opt/。 - 修改distcc的配置文件:
修改/etc/default/distcc,将
STARTDISTCC设置为true;
ALLOWEDNETS为连接的客户端范围,按需设置;
LISTENER为侦听地址,设置为本机ip地址;
JOB为同时可承担的编译任务数目,一般设置为CPU个数+2。
修改/etc/init.d/distcc,将
PATH参数加入步骤2的交叉编译工具链编译器位置,以使distcc在接到编译任务时,能找到对应的编译器。 - 启动distcc服务: sudo service distcc start
发出编译请求的客户端还需要进行如下部署步骤:
- 创建交叉编译工具至distcc的链接:
将交叉编译工具全部链接至distcc:cd /usr/lib/distcc ln -s ../../bin/distcc arm-eabi-addr2line ln -s ../../bin/distcc arm-eabi-ar ln -s ../../bin/distcc arm-eabi-as ln -s ../../bin/distcc arm-eabi-c++ ln -s ../../bin/distcc arm-eabi-c++filt ln -s ../../bin/distcc arm-eabi-cpp ……
- 修改android编译脚本,使其支持distcc编译:
将build/core/combo/TARGET_linux-arm.mk中的TARGET_TOOLS_PREFIX变量改为/usr/lib/distcc/arm-eabi-
修改build/core/definition.mk, 修改transform-d-to-p为:define transform-d-to-p $(hide) if [ -e $(@:%.o=%.d) ];then cp $(@:%.o=%.d) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ rm -f $(@:%.o=%.d);else cp $(notdir $(@:%.o=%.d)) $(@:%.o=%.P); \ sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ -e '/^$$/ d' -e 's/$$/ :/' < $(notdir $(@:%.o=%.d)) >> $(@:%.o=%.P); \ rm -f $(notdir $(@:%.o=%.d));fi endef
- 修改环境变量:
修改PATH,将distcc编译器路径加入PATH的第一个,并加入交叉编译器路径:
export PATH=/usr/lib/distcc:<上述第二步交叉编译工具链位置>:$PATH
此命令可写入profile。
修改DISTCC_HOSTS,指明支持分布式编译的主机地址:
export DISTCC_HOSTS=’localhost … … ‘ - 发起编译过程:
make -j8 CC=distcc 根据编译池主机数和本机资源情况调整job数目,以获取最佳性能。
与ccache配合使用
因android官方已经在构建环境中加入了ccache支持,故可以很简单的打开ccache功能以提高编译效率。具体方法为:
$ export USE_CCACHE=1 $ export CCACHE_DIR=/path_of_your_choice/.ccache $ prebuilt/linux-x86/ccache/ccache -M 20G
其中,20G为推荐值,事实上可以根据编译机器的具体情况进行调整。
在编译期或编译结束后,可以用“ccache -s”命令查看缓存命中情况。
用dmucs实现负载均衡
选中某台主机作为dmucs服务器。进行配置:
- 修改/etc/default/dmucs,启用dmucs:
将SERVER改为yes - 修改/etc/dmucs.conf 文件,配置编译池:
根据文件原有说明格式,加入编译池中的主机。 - 启动dmucs服务:
service start dmucs - 在每个编译主机上执行负载发布客户端:
loadavg -s 主机地址 &
此时,即可以在发起编译时使用
make -j8 CC=gethost distcc
来启用支持负载均衡的分布式编译过程了。
FAQ
- 执行pump时报python错误这是一个已知的bug,解决方法参见https://bugs.launchpad.net/distcc/+bug/511585
- 编译时pump报主机不支持cpp
在创建环境变量时需要指明主机支持的编译类型如:
export DISTCC_HOSTS=’localhost compilehost,lzo,cpp’
参考文献
- distcc官方网站:http://code.google.com/p/distcc/
- distcc官方文档:http://distcc.googlecode.com/svn/trunk/doc/web/index.html
- 《分布式编译环境中的负载均衡 》:http://www.ibm.com/developerworks/cn/aix/library/0905_yangyi_distcc/index.html
- dmucs官方网站:http://dmucs.sourceforge.net
共产共妻
iphone4s发布了,jobs死了。大家一面从众缅怀一代疯子的逝去,一面调戏着他留下的siri。
以前经常看到类似“书与老婆不外借”的标语。上次某天看到一辆小车屁股后面贴着“车与老婆暂不外借”。恍然间似乎明白随着时间的推移,大家的精神洁癖已经慢慢的转换了方向。
但当每个人都在津津乐道于发着女声的siri是多么的善解人意的时候,却似乎把这种精神洁癖抛向了一边。懵懂的以为这曼妙的女声只是为这个持有iphone4s(至少暂时是只支持这个)的我所有。一句一句的调戏着这个电子世界中刚出世不久的loli:
这~~~这到底是怎样的一种欲拒还迎啊。简直是将要实现那种男人禁室栽培的梦想的玩意儿啊!!
然后,技术人员的失败就体现出来了:
大家调戏的,不是同一个Matirx么。好吧,也许它运行在不同的服务器中的不同的线程中…… 但,不可否认的。不论谁问这同一个妞:” Who is your daddy?”, 她都只会说:”You are~” 此时,640×960的屏幕中映射出的油津津的脸上,就浮现出一丝易察觉或者不易察觉的笑容出来了。
这是真实的世界。
问题的提出
问题的起因是我在应用中使用了hessdroid。 在创建远程调用的本地代理时,在Froyo以下版本抛出了一个异常:
08-11 23:58:38.381: ERROR/AndroidRuntime(486): Caused by:
java.lang.IllegalArgumentException: android.engine.BC is not visible from class loader
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
java.lang.reflect.Proxy.getProxyClass(Proxy.java:120)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
java.lang.reflect.Proxy.newProxyInstance(Proxy.java:230)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
com.caucho.hessian.client.HessianProxyFactory.create(HessianProxyFactory.java:346)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
com.caucho.hessian.client.HessianProxyFactory.create(HessianProxyFactory.java:320)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
com.bee2c.android.engine.HessianAgent.(HessianAgent.java:34)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): at
com.bee2c.android.engine.HessianAgent.(HessianAgent.java:21)
08-11 23:58:38.381: ERROR/AndroidRuntime(486): … 9 more
刚开始以为是hessdroid的问题, 于是替换了官方的jar包,结果抛出了另外的java.lang.ClassNotFoundException异常。 而这一切,在froyo下面都是不存在的。
问题的分析
于是把hessdroid的源码并入当前项目,进行单步调试。发现其调用到了如下的代码:
public T create(Class api, String urlName) throws MalformedURLException { return create(api, urlName, Thread.currentThread().getContextClassLoader()); }
而其中 Thread.currentThread().getContextClassLoader() 的返回值为系统类加载器,而不是当前app的线程加载器。于是针对这个问题google了一下。总算发现是由android本身虚拟机的一个bug造成的。
问题的解决
由于上面方法所引用的方法也是一个public方法:
323 324 | public <t>T create(Class</t><t> api, String urlName, ClassLoader loader) throws MalformedURLException </t> |
所以在使用时直接传入了getClass().getClassLoader()。 经验证,问题解决。
出于同样的bug所致,某些第三方jar包抛出的java.lang.ClassNotFoundException可以通过在activity的onCreate中加入如下代码解决:
/* * Ensure the factory implementation is loaded from the application * classpath (which contains the implementation classes), rather than the * system classpath (which doesn't). */ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
阿弥陀佛~
关于房子
吾闻之曰:“非无安居也,我无安心也;非无足财也,我无足心也。”
——墨子《亲士》
今天听到一个房产中介说了这样的话:“很多人都会说现在的房子有感情啊…… 但到了新的大房子看看,回来就觉得房子不那么有感情了”。
android开发书籍emule下载链接
本来放在Verycd的,出于避免某些难以预料的问题的考虑(就像Verycd的诸多电影资源一样),我不得不觉得应该将Verycd作为一个备选方案。而主要在这里进行更新:
入门书籍
ed2k: [android.开发书籍].Beginning.Android.4.pdf
ed2k: [android.开发书籍].Android.for.Programmers.pdf
ed2k: [android.开发书籍].Beginning.Android.4.Application.Development.pdf
ed2k: [android.开发书籍].Beginning.Android.2.(Apress,.2010,.1430226293).pdf
ed2k: [android.开发书籍].Hello.Android.3rd.Edition.pdf
ed2k: [android.开发书籍].Android_Application_Development_For_Dummies.pdf
ed2k: [android.开发书籍].Android.User.Interface.Development.Beginners.Guide.Feb.2011.pdf
ed2k: [android.开发书籍].OReilly.-.Learning.Android.pdf
ed2k: [android.开发书籍].Android Apps for Absolute Beginners.pdf
ed2k: [android.开发书籍].Beginning.Android.3.pdf
ed2k: [android.开发书籍].Programming.Android.pdf
ed2k: [android.开发书籍].Programming.Android.Jul.2011.epub
ed2k: [android.开发书籍].Programming.Android.mobi
稍微深入的书籍
ed2k: [android.开发书籍].Pro.Android.4.pdf
ed2k: [android.开发书籍].Android.NDK.Beginner's.Guide.pdf
ed2k: [android.开发书籍].Android.in.Action.3.pdf
ed2k: [android.开发书籍].Android.in.Action.2.pdf
ed2k: [android.开发书籍].Professional.Android.2.Application.Development.(Wrox,.2010,.0470565527).pdf
ed2k: [android.开发书籍].The.Android.Developers.Cookbook.pdf
ed2k: [android.开发书籍].Practical.Android.Projects.pdf
ed2k: [android.开发书籍].Pro.Android.3.pdf
ed2k: [android.开发书籍].Android.Recipes.epub
ed2k: [android.开发书籍].Android.Recipes.pdf
ed2k: [android.开发书籍].Android.3.0.Application.Development.Cookbook.Jul.2011.pdf
专项书籍
ed2k: [android.开发书籍].Beginning.Android.Tablet.Programming.pdf
ed2k: [android.开发书籍].Pro.Android.Apps.Performance.Optimization.pdf
ed2k: [android.开发书籍].Practical.Android.4.Games.Development.pdf
ed2k: [android.开发书籍].Beginning.Android.4.Games.Development.pdf
ed2k: [android.开发书籍].Apress.Pro.Android.Media.Dec.2010.pdf
ed2k: [android.开发书籍].Pro.Android.Web.Apps.Develop.for.Android.using.HTML5,.CSS3.&.JavaScript.pdf
ed2k: [android.开发书籍].Beginning.Android.Games.pdf
ed2k: [android.开发书籍].Pro.Android.Games.-.Vladimir.Silva.pdf
ed2k: [android.开发书籍].Android.Application.Testing.Guide.-.Diego.Torres.Milano.pdf
神奇的存在
ed2k: [android.开发书籍].Learn.Java.for.Android.Development.pdf
Yum出个Fedora 15来
Fedora 15 还有一个多星期才能正经的冒出来(如果没意外的话)。当然,如果依照惯例偷跑,可能会提前个几天。反正大概意思就是,其实现在的版本跟最后的发布版变化应该不会太大了。所以,如果拥有足够的好奇心并且足够贪玩,现在已经是升级到Fedora15的Deadline了。
因为自从Fedora发布新的alpha版本之后,rawhide库里面就已经是下下个版本的内容。所以如果很想当然的打开rawhide,然后yum upgrade一下,就会很“欣喜”的发现自己已经开始使用一个宛如旺鸡蛋的Fedora 16了。
所以要遵循如下步骤来yum:
- 洗手! 没错!不但饭前便后要洗手,每当你怀疑自己人品的时候,洗手总是最好的保证。当然,别忘记擦干净,除非你的键盘是防水的。
- 找到一个Fedora的镜像,比如 http://mirrors.163.com/fedora/
- init 3,并验证网络链接正常。否则更新到X相关的包,有可能会XXXOOO~~~
- rpm -Uvh 对应的fedora-release* 包, 比如,如果你是i386的,就可以用http://mirrors.163.com/fedora/development/15/i386/os/Packages/fedora-release*
- 人品的开始 yum upgrade。 这其中必然会报n多的错误,不妨把有冲突的包干掉,以后慢慢补上。
我是大概两周前做了上面的事情,所以,如您所见,我现在还能在网上胡扯,说明后果是可以承担的:
感想:
- 原来用Compiz Fusion总是习惯戳屏幕的右上角,突然改到左上角了,还真TMD不习惯。
- Gnome Shell使用起来,至少是目前,还是感觉不如Compiz Fusion方便。
- Gnome Shell可以做屏幕录像啊!!!Control+Shift+Alt+R
- fcitx不知道为啥只能在firefox下用 o_O。
华为HG8245获取telecomadmin密码的方法
光进铜退,很多同学的路由换成了HG8245,可如果一不小心在破解路由之前就连上了网络,而人品又不是那么好的话,telecomadmin的默认密码(admintelecom或nE7jA%5m)就会被远程的改掉。 有些同学说可以打10000号报修,或者给安装的小伙子抛媚眼,但伟大领袖毛主席教导我们说: 自己能做的事情自己做! 于是,我们这么做:
怎么折腾ip我就不说了,首先:
telnet 192.168.1.1 <–有的是 192.168.100.1
用户名 root
密码 admin
此文不明示、暗示任何保证阅读者都能搞定,一切都和人品相关。 切切~











