LoginSignup
29
17

More than 5 years have passed since last update.

NimとCでもWebAssemblyやってみた

Last updated at Posted at 2017-03-14

http://qiita.com/akira_/items/55cf1f5911b14e265c6f
こちらの記事に触発されてNim版とC版書いてみました。

まず結果

fibonacci(45)の結果です

環境

CPU: Intel Core i7-6700
RAM: 8GB x2
WebBrowser: Google Chrome 57.0.2987.98 (64-bit)
Language Elapsed
JavaScript 19.176
C Wasm 4.357
Rust Wasm 4.354
Nim Wasm 4.359

結果については、あくまで一回実行したものを貼っているだけで、実行環境と、実行するごとに結果が変わることをご了承ください。

ソースコード

# Nim
import os
import times
import strutils

proc fibonacci*(n: int64): int64 =
  if n <= 1'i64:
    1'i64
  else:
    fibonacci(n - 1'i64) + fibonacci(n - 2'i64)

proc main() =
  let args = commandLineparams()
  let n = args[0].parseInt()
  echo "fibonacci($#) = $#" % [$n, $fibonacci(n.int64)]

main()
// C
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>

int64_t fibonacci(int64_t n) {
    if (n <= 1) {
        return 1;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

int main(int argc, char** argv) {
    int n = atoi(argv[1]);
    printf("fibonacci(%d) = %" PRId64 "\n", n, fibonacci(n));
    return 0;
}

手順

上記の記事ではDockerイメージを使ってビルドされたようですが、自分はVM上のXubuntuにemsdkを使ってインストールしたものをビルド環境として使用しました。

RustやNimなどの各種言語のコンパイラのインストールに関しては省略します。

Emscriptenのインストール

http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html
からemsdkをダウンロード、展開し、PATHを通します。

PATHを通したら

$ emsdk update
$ emsdk install sdk-incoming-64bit
$ emsdk activate sdk-incoming-64bit

でEmscripten本体のインストールと有効化ができます。

追記
この後に

$ source emsdk-portable/emsdk_env.sh

が必要なことを書き忘れていたので追記しておきます。
~/.profileなどに書いておくのがいいと思います。
追記ここまで

Emscriptenについては、sdk-incoming-64bitならWebAssemblyのバージョンフラグがちゃんと1.0になっているようです。(2017/03/14時点)

ここで注意点としては、Emscriptenだけでなく、LLVMとClangのビルドが走るので、時間がかかるのとメモリを大量に消費します。
メモリに関してはスワップを用意するか、そもそも大量に用意しておくかで対処しましょう。(自分はVMに10GBのメモリを割り当てて対処しました)

あとは言語に合わせてコンパイラを走らせるだけです。

# C
$ emcc -O3 -s WASM=1 -o fib-c.js fibonacci.c
# Rust
$ rustc -O --target=wasm32-unknown-emscripten -o fib-rust.js fibonacci.rs
# Nim
$ nim c -d:release -d:emscripten -o:fib-nim.js fibonacci.nim

Nimの場合は以下のnim.cfgをソースと同ディレクトリに置いておきます。

@if emscripten:
  cc = clang
  clang.exe = "emcc"
  clang.linkerexe = "emcc"
  clang.options.linker = ""
  cpu = "i386"
  warning[GcMem]= off
  passC = "-s WASM=1"
  passL = "-s WASM=1"
@end

感想

  • Emscriptenのビルドがただひたすらに重いのでつらい
    • Emscripten以外のto Wasmコンパイラの選択肢が欲しい気がする
  • とりあえずWebAssembly使えば現代のコンパイラのおかげか結構高速に動いてくれるので良い
  • 初回のEmscriptenを使ったコンパイルは時間がかかるが、2回目以降はどれも長くても5秒以内でコンパイルしてくれる
    • 特にNimはインクリメンタルコンパイルがあり、Rustも開発中なので大きいプログラムでも問題になることはなさそう

まとめ

JavaScript、C、Rust、そしてNimの4つの言語のベンチマークをやりましたが、この記事はNimに興味持ってもらうために書いたようなものだったりします。現状WebAssemblyができる言語はC/C++/Rustしかないという認識が一般的なようですが、Nimも一応できるということを知ってもらえれば幸いです。(GCちゃんと動いてるかはっきりしてませんが・・・)
一応Nimでもjsbindとかを使えばDOM操作できたりします。

特にNimはGCありなのでC/C++/Rustよりも書きやすいと思っているので、WebAssemblyで手軽に高速化する言語としての選択肢になってほしいなとか勝手に思ったりしてます。

最後に

お手元のブラウザで手軽に試せるようにWebAssemblyのベンチマークができるサイトを作りました。

雑な作りではありますが、とりあえず動かしてなんとなく雰囲気を感じてもらえれば幸いです。

注意点として、雑な作りなのでWasmのパースからベンチマークしていて、それのせいでNが小さいとJavaScriptより遅くなってしまっています。 40 <= N <= 46ぐらいをおすすめします。


自分はJavaScriptを書くたびに心が削れていく人なのでWebで色んな言語が動くのが当たり前になる日がくるといいですね。

29
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
17