聊聊2017年做得三件技术上的改进

2017年也如同其他年份那样,渐渐远去。技术上的工作内容总还是重覆的多,但还是做了些改进。这些想法其实在我脑中很久,总是因为各种原因和阻力得不到实现。2017算是对自己有个交待了。

 

二方库开发

可能“第三方库”大家听得多,二方库是说在同一个组织里开发的,用于其他产品的代码库。说白了,就是共同代码提取。

把这事做成阻力远比当初想的大。这不是一个技术问题,或者说技术上不是大问题,更多的是一个软件组织分发、资源分配、挑战现状的问题。在组内大量讨论,和各老板做说明演示后,终于,老板们同意了!至少在我负责的产品里,做现有共同代码的提取,并用独立的项目发布周期维护。

大家给这个项目起了个名字叫“Kona”,是一个Hawaii的岛,那也产咖啡。😀

桌面端开发引入Web技术

其实这是我很久以来的想法,几年前就做了些实验,积累了些经验。结合Web容器,就可以利用大量现有的Web框架和技术,使前端体验大大提升,也可以提高开始的效率。在我”强烈”的推动下,终于把AngularJS+Bootstrap塞到了JavaFX的WebViewer里,收获了些好评。虽只能算是向前迈了一小步,但希望之后的步子能大些。现在组里的同事学习Web技术的热情高涨。

引入Kotlin

感谢Google在2017 I/O大会上把Kotlin提升为未来要支持的一级语言。我在关注Kotlin多年后,终于到了最后一个重要的理由把它引入到开发中。虽然只是先用来做Unit Testing,但之后,我相信使用的地方会更多。它的很多特性绝对是大大的提高“生产力”,同时产出更多安全的代码。

之后。。。

可能这些东西,把别的公司看来都不算什么,技术上并没有什么高深的玩意。但对于我个人,看着这些多年来的想法得以实现,感觉还是很好的。现在很多旧项目占去了大量的时间和精力,要挤出时间想想之后的事情了。希望能有好运气吧!Finger crossed!🖖

ND4j的CPU与GPU简单性能对比

最近在学习Deep Learning。ND4j是一个类似于Python Numpy的Java版本实现,支持CPU和GPU Backend。很是好奇,这两者性能到底能差多少,于是做了一个小的测试。

安装CUDA Toolkit 8.0

最新的CUDA Tooklit版本是9.1,但是目前最新ND4j的Release版本(0.9.1)还不支持。(看了ND4j论坛里的讨论,master branch已经支持9.1)0.9.1只支持CUDA 7.5和8.0,我的实验中,安装了8.0版本。在这里下载Installer和Patch。

安装完成后,机器要重启一下。

ND4j的Maven配置

在Maven里通过切换Nd4j的artifactId来设置CPU或GPU Backend。

nd4j-native-platform是CPU Backend,nd4j-cuda-8.0-platform是GPU Backend。

一个简单的测试

下面是一个简单的测试代码,两个10K by 10K的Matrices做Outer Product。

我的CPU是i7-5820K,GPU是GTX 970 3.5GB。测试结果真的非常让人吃惊 – GPU 497ms, CPU 7827ms. 差了约16倍。

我终于知道NViDIA的股价为什么涨这么多了!😁

 

Visual Studio Code – Better than Atom

之前推荐过Github的Atom,但之后它的表现不太让人满意,真的非常非常的慢!!

再之后就开始使用Visual Studio Code,非常惊艳的Microsoft产品,运行很快,各种插件也很全,还能跨平台。现在已经全面用它来替代Atom和Notepad++,大家也快去试试吧!😬

用SWTBot+Junit+Truth做GUI层面的Unit Testing

在开发组里,Unit Testing的方法已经深入人心,Case的数量也越来越多。可因为GUI层面代码的特殊性,目前大多数的测试都针对非GUI层面的Code。这使得占总代码量40%的GUI层面很少被单元测试覆盖。

本文通过一个简单的例子,结合SWTBot,Junit和Truth,实现了GUI层面的单元测试。

SWTBot的安装

SWTBot可以通过Update Site(http://download.eclipse.org/technology/swtbot/releases/latest/)安装。

在开发项目中也要加入SWTBot的依赖,

一个简单的Dialog

让我们来实现一个简单的对话框,用来做两个数的加法。

代码如下:

这里特别使用了setData方法对几个关键的控件设置了“id”,这是为了能在SWTBot中更方便准确的定位待测试的控件。

SWTBot+JUnit+Truth

待测的对话框已经准备好了,下面来写一个简单的单元测试。

几点要注意的地方,

  • 测试Dialog时,要使用setBlockOnOpen(false),否则open()方法会把后续测试代码阻塞掉。
  • SWTBot搜索控件的办法有几种,以Text控件为例,介绍几个常用的。
    • text()等价于text(0), 就是找第一个Text控件
    • text(n), 按顺序找第n个控件
    • textWithLabelInGroup(label, inGroup)等价于textWithLabelInGroup(label, inGroup,0),就是找在某个Group里的第0个Label为”label”的Text控件
    • textWithLabelInGroup(label, inGroup,n),就是找在某个Group里的第n个Label为”label”的Text控件
    • textInGroup(text, inGroup)等价于textInGroup(text, inGroup, 0), 找在某个Group里第0个text为“text”的Text控件
    • textInGroup(text, inGroup, n), 找在某个Group里第n个text为“text”的Text控件
    • textWithId(key, data), 找出key=data的Text控件。这就是和前面setData()相对应的一个API。用ID找还有一个更简单的API–textWithId(value),这个API没有输入key,原因是SWTBot有个Preference给DEFAULT_KEY–org.eclipse.swtbot.search.defaultKey,默认的值为
      “org.eclipse.swtbot.widget.key”
  • 对不同的控件,API会略有不同,不过大同小异。SWTBot现在除了支持基本的SWT控件外,还支持了Nebula Grid,NatTable,GEF等复杂的控件。
  • 写Assertion的部分和普通的Unit Test并没有什么不同。
  • 因为这种Unit Test的写法和普通的JUnit并没有什么不同,所以Headless Build就可以用一般maven test。当然,如果是开发RCP应用,一定要使用Eclipse Tycho插件。
  • 还有一点不同的事,SWTBot的Case一定要在X环境下。如果Build Server上并没有开X环境,需要要安装Xvfb

总结

通过一个小例子,本文讨论了如何使用SWTBot对小型的SWT开发单元,如对话框、Composite等,进行单元测试(SWTBot也可以测试完整的大型应用)。

现在可以慢慢完善GUI层面的单元测试了,下一步也许可以和Cucumber之类的Framework结合起来。😁

 

 

 

对Python脚本做简单的profiling

最近事情好多,Blog好久没有更新了。今天上来写写最近解决的一个Python里的性能优化问题。

起因

之前为项目写过一个Sqlite数据库预处理的Python脚本,里面主要做了张新表,把其他表的数据填进去。当时主要考虑到维护性,条理清楚,就没太考虑Performance。之后QA发现模块的运行比原来慢了20倍,因为还是挺快,所以没有当时马上修正。

Profiling

这次Release要修掉这个问题。我的原则是,改进Performance一定要做Profiling,做到有的放矢才。

和Java的VirtualVM类似,Python 2.7也内置了几个Module做Profiling,我选择了cProfile。基本就是如下命令:

“-s tottime”是让结果用总执行时间排序。

优化之前的执行结果,

可见罪魁祸首就是sqlite3的Cursor的execute()方法,和原本猜测的也是一样的。优化的手法也很明确就是减少execute()的调用次数,使用batch和合并SQL语句的办法,很容易就用空间换回了时间。

优化之后的结果,

优化之后只是原来的9%的Runtime。

总结

  • 继续坚持用Profiler来做Performance的改进。
  • 边改边用Profiler查看Performance有没有提升。
  • 不要过分优化,否则代码没法看了。😀

References

用Raspberry Pi搭个宝宝视频监视器

现在租住的是一个两层的Townhome,宝宝睡在二楼,有时大人在楼下,真的不放心楼上的宝宝。家里有个旧的Raspberry Pi和闲置的Logitech Web Camera,于是动手自制了一个视频监视器。

器材

Raspberry Pi 2 Model B

Logitech Web Camera C525 (支持720P的视频录制)

很多年前买的,闲置状态。这种Web Camera可以即插即用,不需要安装额外的驱动,很方便。

 

通用USB网卡(从Raspberry Pi 3开始,网卡就内置了,不需要再买网卡)

软件

视频监控主要是要实现视频流(Video Streaming),按这个思路可以找到一些软件,如motion, mjpg-streamer和VLC。对比之后,感觉mjpg-streamer比较适合,功能强大,配置简单。

编译安装mjpg-streamer

这里有篇非常好的帖子,step by step的教你安装。详见

运行mjpg-streamer

我写了一个init.d的启动脚本,可以让raspberry在启动时就自动运行mjpg-streamer。

在/etc/init.d/目录下,新建一个脚本mjpg_streamer

脚本中,使用了nohup,可以让mjpg-streamer成为daemon进程。

再运行命令

就可以把这个脚本加到默认run level(2)的启动项里。

结果

一切就绪,全家就可以在各种设备上看到宝宝了。缺点是还没有声音,下一步的功课吧!也许要用到vlc。😁

Screenshot_20160705-223049

Hello World from Henry!

好久没有写博客,因为家里多了一位新成员–Henry。我也难得有机会休假,全心全意地照顾家人,当全职奶爸,做饭,换尿布,拍嗝,乐在其中!😁

Henry的预产期本来是6月15号,双子座。没想到拖了一周,成为巨蟹座,可能是也想像他老爸我一样当暧男吧(我可能自以为是了😄)。头两天他吃不饱,很闹,着实有些崩溃,我有一段时间觉得前途灰暗。尤其是第一天,当我28个小时没睡觉,Henry还在哭闹时。但即使那样,我当时依然有信心把Henry照顾好,把Yolanda照顾好。后面妈妈的母乳来了,Henry吃的很开心,变身成了天使娃,能吃能睡能拉。高兴的同时,我也更有信心了,以后教他编程、摄影、篮球和做饭。

现在,Henry已经两周大了!可爱吧!😁

I'm watching you!

 

2s

好用的Spacemacs!

作为Emacs粉,以前最麻烦的莫过于安装各种package和设置各种配置,常常把各种文件拷来拷去的。偶然的机会看到了Spacemacs这个项目,试用之后,感觉真是非常方便。

  • 安装简便,基本就是用git clone得到最新的版本,还可以简单的升级。
  • 默认的配置非常好用,反正比我之前的好,我在配置包丢在网盘上了。😁
  • 安装package非常简单,基本就是几条命令,再不用网上找各种包了。
  • 强大的个人定置,可以分Layer。但其实对我没什么用,基本的已经很好了。

Emacs粉应该果断试试,不会让你失望的!戳这!😋

 

Java坑之Class.isEnum()

发现在这个坑是因为代码里用到了cloning库

在做深度代码拷贝时,发现Enum对象也被Copy了,破坏了Enum对象的唯一性。读了cloning的源代码,其实它考虑了Enum的问题,默认也是跳过的。在其1.9.0版本,它使用了Class.isEnum()来检查,但在1.9.2版本中,检查的代码换成了instanceof Enum, 问题也解决了。对比一下,两种API的区别,

输出是

第二行的输出居然是false, 再看看A2的类签名,不是A,而是一个匿名类A$1。这都是因为A2有Override toString方法,Java产生的了一个匿名类。再看看isEnum的实现,

这下都清楚了,JDK里使用通过基本类是否是Enum的方法,判断当前类是否是Enum, 但当有匿名类的出现,父类就不再是Enum,isEnum的检查也就失效了。

难道Enum的匿名类就不是Enum了吗?😈

这个坑大家要小心啊!