golang vs rust vs javascript

最近研究了几天rust,并不是特别的深入,主要用来做wasm。 之前的部分关键程序使用golang写的,但不是wasm,也简单封装了接口, 试了下wasm。

就体验而言,rust的学习曲线实在太抖,相比之前的golang学习,golang用个个把小时看下语法,结构,项目组织方式,然后就可以做 项目了。rust看了几天,貌似还在门外徘徊,不过没关系,经过几天的摸索,我终于学会了使用rust来编写wasm,并且和elementui的 框架的配合调整为我想要的了。而这个只是灾难的开始。

我想试着用rust,一个主要原因是golang生成的wasm实在太大,什么都不做的2MB+了。另外一个最重要的原因是golang生成的wasm, 在解析一个很大的json字符串的时候,竟然需要13+秒的时间,如果使用第三方的json解析的话,需要1+秒的时间,虽然可以使用tinygo 来减少wasm的容量,但tinygo无法使用第三方的json解析。而在查看wasm相关信息的时候,rust据说不错。所以就决定写个试试了。

下面的坑都是根据回忆记录的。不一定是对的,所有执行的目标都是wasm

  1. rust的json解析,如果不使用js_sys的json解析的话,需要很长的时间,没记错的话,需要很久,至少10s+是有的。这个json数据大约在几十MB之间。 如果使用js_sys的话,需要0.8秒左右的时间。之所以提出来是因为太明显了。最后逼迫我必须使用js_sys的解析。缺点就是描写的各种累心
  2. 因为1解析出来的json数据会被各个不同的部分使用,因此这个变量要被全局存储。全局存储大概搞了我好多天,因为没有最理想的。 刚开始准备一个最简单的Option的方案,不支持指针类的; 升级为lazy_static方案, 不支持js_sys::JsValue,JsonValue太慢 放弃; thread_local方案,这个需要使用with,这个是我目前可以找到的可以支持js_sys::JsValue的了,也只能这样用了,使用with, 丑就丑吧
  3. 因为2使用了with方案,而代码中的数据在处理的时候,会从其他地方得到的数据进行整合,比如我又从其他的公共变量获取数据,而 with的处理结果,除非使用clone的方式,否则由于变量生命期的关系,各种编译报错,我真的恨死rust的这种反人类的设计了。 明明我只是为了读取内部的一段内存的数据,结果非的逼我clone出一段内存来,感情现在内存真的都是白菜价啊
  4. 很无奈,其他部分(我只测试了一个,以后的以后想办法对付吧),我使用了lazy_static方案,我试了下Mutex,结果在浏览器里 一跑,发现浏览器cpu 100%卡住了,等好久才有反映,这下好了,整个数据不用处理了。既然Mutex不行,就试试RwLock,反正我 数据仍到HashMap中,更新少,查询多,但要返回相应的数据,还得clone,于是又回到3了。
  5. 我无数次准备掐死自己的心都有了,让你犯贱选rust,你看使用golang多少,一周的rust研究成功,golang两个小时就达到相同效果了。 但golang真的慢啊
  6. rust的设计初衷或许非常完美,但智能指针的设计模式或者所有权的设计,真的是非人类。即使是学院的erlang,也没有rust这么变态, 我感觉我好久都没关注过erlang了,真有点怀念熟悉了之后处理代码的那种感觉。

element-ui使用 rust wasm

趁着没有忘记,赶快记录下来。

前两天试了下wasm,刚开始使用golang随便写了个,直接html加载没有问题, 但golang的版本太大了。 tinygo的版本库支持有问题。正好最近在看rust的编程。就试试rust吧。

我项目使用的是element-ui, 无它,关键是懒。里面的很多数据处理部分,vue的尿性,造成json所占的 内存过大,动不动就要500MB甚至上G的内存都很正常,没办法,我一个json原始的数据结构都要50多MB了。

目的是为了解决内存以及效率。所以试试wasm吧

首先遇到的坑:

  1. rust的编译要用下面的方式:

    wasm-pack build
    

    也就是没人的target参数为bundler的方式, 试对这一步就已经成功了一半了。我不知道其他的为啥和 element-ui有冲突,反正这个可以了。其他的我除非使用原始的html的script type=”module”去加载 等等,否则不可以

  2. 引入方式的修改 我不知道做成npm发布包会如何,我更喜欢直接copy文件夹的形式,因为我的前端和rust等各部分都是分别 在不同的docker中进行开发的,但如果import编译出来的wasm.js文件的话,会报后面提到的错误。 因此需要新建一个文件(这里是index.js),内容很简单:

    export default import('./pkg/wasm.js');
    

    引用及测试:

    import wasm from './wasm/index.js';
    (async _ => {
      const module = await wasm;         //引入wasm对象
      module.greet("aaaaaa");
    })();
    

    上面用的是rust的那个helloworld的,也是默认生成的模板代码

  3. vue.config.js的修改 碰到以下的错误:

    WebAssembly module is included in initial chunk.
    This is not allowed, because WebAssembly download and compilation must happen asynchronous.
    Add an async splitpoint (i. e. import()) somewhere between your entrypoint and the WebAssembly module:
    

    对于element-ui而言,需要在js的处理里面屏蔽掉生成的代码, vue.config.js 中chainWebpack部分添加 以下代码:

    config.module
          .rule('js')
          .exclude.add(resolve('src/wasm'))
          .end()
    
  4. 如果像我一样,使用docker部署的话,开发模式也是在docker里面的话,重启开发模式,否则vue.config.js不生效