首先声明这篇不是批判google native client的文章,只是最近暂时接触了一下nacl后的一点疑惑
第一次知道google native client是在暑假的时候,但是那时候没有怎么去关注,直到最近在看一个要很大计算量的东西,于是想起了这个nacl。因为它最诱惑人的就是能够用c/c++来写应用的代码,编译成native code后的速度比js快上很多。
native client的technique overview中如下写道
- Existing software components: With its native language support (currently, C and C++ in the SDK), Native Client enables you to reuse current software modules in a web app—you don't need to spend time reinventing and debugging code that's already proven to work well.
- Legacy desktop applications: Native Client provides a smooth migration path from desktop application to web app. You can port and recompile existing code for the computation engine of your application directly to Native Client, and need repurpose only the user interface and event handling portions to the new browser platform.
- Enterprise applications that require heavy computation: Native Client handles the number crunching required by large-scale enterprise apps. To ensure protection of user data, Native Client enables you to build complex cryptographic algorithms directly into the browser so that unencrypted data never goes out over the network.
- Multimedia apps: Codecs for processing sounds, images, and movies can be added to the browser in a Native Client web app.
- Games: Native Client enables a web app to run close to native speed, reusing existing multithreaded/multicore C/C++ code bases, combined with low-level access to low-latency audio and (coming soon) networking APIs and OpenGL ES with programmable shaders. Programming to Native Client also enables your binary to run unchanged across many platforms. Native Client is a natural fit for running a physics engine or artificial intelligence module that powers a sophisticated web game.
这几点都是很吸引人的。能够利用现有的C/C++组件, 比如ogre, bullets physic engine,能够移植原有的桌面应用(当然所有操作是要在sandbox内进行并且安全的),加速视频,音频,图片等计算密集型的处理等等。在这个富客户端应用越来越多,js越来越不堪重负的时代,将很多计算交给native client来处理是很好的一个选择。
于是我下了sdk,写了一个hello world后开始尝试能不能把现在的很多Web 3d应用中需要的矩阵运算放入c++中,再用js和native client通信计算这些计算量相对较大的东西。js和native client的通信是通过一方PostMessage,另一方加一个事件处理函数来接收这个message来进行的,跟WebWorker差不多。PostMessage能够接受的参数只有一些基本类型,比如整数,浮点数,字符串。对于数组和对象只能够格式化成一个json字符串来传递。
js中json格式的处理比较简单,只要使用JSON.stringify和JSON.parse就行了,但是使用pepper API的c++没有现成的可以操作json的lib,只能去找来了jsoncpp这个开源的lib来解析json数据,第一次成功的看到js alert出了nacl传过来的json object还是很开心的。毕竟这样就能够自由的通信处理任何数据了。一阵激动之后马上就在c++中写了一个矩阵乘法的操作,然后用js传送两个矩阵过去,计算之后返回结果,这些都很顺利。但是当尝试着循环做1w次这样的操作后就傻眼了,1w次两个4x4 matrix的乘法花了10s,单纯的用js运算也只是一瞬间的事。c++的效率应该是没有问题的,写的程序也非常简单,不会存在上算法太鹾的问题,于是就只能猜测js和nacl的通信效率没有想象中那么高。
这个问题在nacl的几个sample中都不存在,因为都没有js和nacl频繁的交互,但是我现在更需要的是能够把一些计算密集的操作用c++完成放入nacl,然后提供一个接口能够让js调用,让js来处理ui和逻辑上的问题,这样js肯定会和nacl有频繁的通信,看了几个demo,像bullet physic engine都是直接把整个应用移植成了nacl,而不是封装出几个供js调用的接口,这样如果要展示的话也只能在c++中用opengl es来完成了,还留着外面的html+js+css的空壳应用干嘛呢。
不过我也接触了nacl没多长时间,不知道是否有更巧妙的方法来解决js和nacl交互的问题,或者说我对nacl定位的看法就是错误的,大家觉得这篇文章太偏激的话也勿喷。
还有就是最后编译成的nexe文件忒大了,加了jsoncpp后有近4M,不知道是否有优化的方法。