<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>Emscripten &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/emscripten/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>Webブラウザで高速な演算を可能にする低水準言語asm.jsと、WebAssembly詳解ーC / C++をasm.jsに変換するツールEmscripten</title>
		<link>/chikoski/22494/</link>
		<pubDate>Mon, 20 Feb 2017 00:00:44 +0000</pubDate>
		<dc:creator><![CDATA[清水智公]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Emscripten]]></category>
		<category><![CDATA[asm.js]]></category>

		<guid isPermaLink="false">/?p=22494</guid>
		<description><![CDATA[連載： 低水準言語asm.jsとWebAssembly詳解 (3)間が随分と空いてしまいましたが、低水準言語とasm.jsとWebAssembly詳解の第3回目です。 前回は、型システムを中心にasm.jsを解説しました...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/asmjs/" class="series-384" title="低水準言語asm.jsとWebAssembly詳解" data-wpel-link="internal">低水準言語asm.jsとWebAssembly詳解</a> (3)</div><p>間が随分と空いてしまいましたが、<a href="https://html5experts.jp/series/asmjs/" data-wpel-link="internal">低水準言語とasm.jsとWebAssembly詳解</a>の第3回目です。</p>

<p><a href="https://html5experts.jp/chikoski/18980/" data-wpel-link="internal">前回</a>は、型システムを中心にasm.jsを解説しました。asm.jsはプログラムの中に型が明示されるため、事前コンパイルをして高速に動作させられる点がasm.jsの大きな特徴でした。</p>

<p>しかし数値演算しか行えなえず、また式にすべて型アノテーションを行わなくてはならないため、通常のJavaScriptのプログラムのように手で書くのはなかなかに辛いものがあることもわかりました。</p>

<p>これはasm.jsで書かれたプログラムは、JavaScriptとしても実行可能であることが求められたためでもありました。そこでasm.jsよりも書きやすい言語で書かれたプログラムを、asm.jsに変換するツールが提案されています。</p>

<p>そのもっともよく使われている例である<a href="http://kripken.github.io/emscripten-site/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Emscripten</a>について、インストール方法や簡単な使い方、ファイルアクセス、そしてJavaScriptとの相互連携までを解説します。</p>

<h2>トランスコンパイラ Emscripten</h2>

<p>Emscriptenは<a href="https://github.com/kripken/emscripten/blob/master/LICENSE" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">オープンソース</a>のトランスコンパイラで、コンパイラフレームワークである<a href="http://llvm.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">LLVM</a>を利用して実装されています。これを利用することで、C言語やC++で書かれたプログラムをasm.jsに変換できます。</p>

<p>たとえば次のCで書かれたHello,worldもEmscriptenを使うと、asm.jsに変換され、Node.jsやWebブラウザで実行できます。</p>

<p></p><pre class="crayon-plain-tag">#include &lt;stdio.h&gt;
int main(int argc, char** argv){
  printf("Hello, world!\n");
  return 0;
}</pre><p></p>

<p>変換に利用するのがEmscriptenのフロントエンドである<code>emcc</code>コマンドです。これをgccのように使って、.cファイルをコンパイルします。次の例では、上記のHello,worldをasm.jsに変換し、Node.jsで実行しています。</p>

<p>3行目に出力されている&#8221;Hello,world!&#8221;は、Node.jsが出力しています。Cで書かれたプログラムが、Node.jsの上で動作する、というのはなかなか味わい深いものがありますね。</p>

<p></p><pre class="crayon-plain-tag">$ emcc -o hello.js hello.c
$ node hello.js
Hello, world!</pre><p></p>

<p>Emscriptenは、自分の書いたプログラムだけでなく、libcやlibc++といった標準ライブラリも一緒に変換します。</p>

<p>上記の例ではCの標準関数も一緒に変換が行われているため、<code>printf</code>が正しく実行されています。</p>

<p>またOpenGLの関数呼び出しはWebGLへ変換されます。<a href="https://www.libsdl.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SDL</a>の関数も利用できるため、<a href="https://github.com/kripken/emscripten/blob/master/tests/hello_world_sdl.cpp" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">次のようなSDLを用いたプログラム</a>も変換できます。</p>

<p>これらはCanvas要素をディスプレイ代わりに利用するため、変換時にJavaScriptだけでなくHTMLも合わせて出力させることで<a href="https://chikoski.github.io/wasm-demo/hello-sdl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">実行</a>できます。</p>

<p></p><pre class="crayon-plain-tag">$ emcc -o hello-world-sdl.html hello-world-sdl.cpp</pre><p></p>

<h2>Emscriptenのインストール</h2>

<p>Emscriptenはemsdkというツールを利用してインストールします。このツールは単なるインストーラではなく、<a href="https://github.com/creationix/nvm" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">nvm</a>や<a href="https://www.rustup.rs/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">rustup</a>、<a href="https://rvm.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">rvm</a>のようなツールで、使用するEmscriptenのバージョン指定や更新を行えます。</p>

<p>emsdkとEmscriptenのインストールは<a href="https://github.com/juj/emsdk" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">配布元のサイト</a>で確認いただけますが、概要を述べると次のようになります。</p>

<ol>
<li>依存するツールのインストール：GCC/Git/Cmake/Python 2.7.x
2.emsdkのクローンと更新</li>
<li>最新版のEmscriptenのインストール</li>
<li>インストールしたEmscriptenの有効化</li>
</ol>

<p>emsdkはGitHubで配布されています。また内部の処理にGitを利用します。またEmscriptenのインストールや更新時にclangのコンパイルを行います。cmakeやgccはそのコンパイルに利用されます。</p>

<p>環境によってインストール方法は異なります。それぞれの環境にあった方法でインストールしてください。<a href="http://brew.sh/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Homebrew</a>を利用できるようになっているmacOSの場合、GCC/Git/Pythonはすでにインストールされています。CMakeは次のように<code>brew</code>コマンドを使ってインストールできます。</p>

<p></p><pre class="crayon-plain-tag">$ brew install cmake # cmake のインストール</pre><p></p>

<p>依存するツールをインストールしたらemsdkをクローンします。</p>

<p></p><pre class="crayon-plain-tag">$ git clone https://github.com/juj/emsdk.git
$ cd emsdk</pre><p></p>

<p>emsdkフォルダ内にある、emsdkというファイルを使って、Emscriptenの管理を行います。</p>

<p>まず<code>update</code>コマンドを実行して、emsdkそのものと、インストール可能なEmscriptenのバージョンリストを最新のものへと更新します。次に<code>install</code>コマンドを実行して、最新の安定板をインストールします。</p>

<p></p><pre class="crayon-plain-tag">$ ./emsdk update
$ ./emsdk install latest</pre><p></p>

<p>インストールしただけでは、Emscriptenを利用できるようにはなりません。<code>activate</code>コマンドで利用するEmscriptenのバージョンを指定し、環境変数を設定することで、インストールした最新バージョンのEmscriptenが利用できるようになります。</p>

<p></p><pre class="crayon-plain-tag">$ ./emsdk activate latest
$ source ./emsdk_env.sh</pre><p></p>

<h2>Hello, world!</h2>

<p>asm.jsへのコンパイルはemccコマンドを利用して行います。まずは正しくインストールできたかどうかを確認するために、バージョン番号を表示させてみましょう。</p>

<p></p><pre class="crayon-plain-tag">$ emcc -v</pre><p></p>

<p>バージョン番号が表示されれば正しくインストールできています。次はHello,worldでしょう。次のようなプログラムを作成し、hello.cという名前で保存します。</p>

<p></p><pre class="crayon-plain-tag">#include &lt;stdio.h&gt;

int main(int argc, char** argv){
  printf("Hello, world!\n");
  return 0;
}</pre><p></p>

<p>プログラムを作成したら、つぎのコマンドを実行します。</p>

<p></p><pre class="crayon-plain-tag">$ emcc hello.c</pre><p></p>

<p>a.out.jsというファイルが作成されます。これが上記のプログラムがEmscriptenによって変換された結果です。nodeで実行させてみましょう。</p>

<p>ターミナルに&#8221;Hello,world!&#8221;と出力されるはずです。</p>

<p></p><pre class="crayon-plain-tag">$ node a.out.js</pre><p></p>

<h2>emcc コマンド</h2>

<p>emccコマンドには、<a href="http://kripken.github.io/emscripten-site/docs/tools_reference/emcc.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">いくつものオプション</a>があります。それらのうち、よく使うものをまとめると次の表になります。</p>

<table>
<thead>
<tr>
  <th>オプション</th>
  <th>効果</th>
</tr>
</thead>
<tbody>
<tr>
  <td><code>-o &amp;lt;file&amp;gt;</code></td>
  <td>出力するファイル名を指定する</td>
</tr>
<tr>
  <td><code>-O0</code></td>
  <td>最適化を全く行わない</td>
</tr>
<tr>
  <td><code>-O1</code></td>
  <td>LLVMの<code>-O0</code>最適化や、アサーションの削除といった最適化が行われる</td>
</tr>
<tr>
  <td><code>-O2</code></td>
  <td><code>-O1</code>に加えて、出力するJavaScriptの最適化も行う</td>
</tr>
<tr>
  <td><code>-O3</code></td>
  <td><code>-O2</code>に加えて、さらなる最適化をJavaScriptに対して行う。遅い</td>
</tr>
<tr>
  <td><code>-g</code></td>
  <td>デバッグ情報を保持する</td>
</tr>
<tr>
  <td><code>--preload-file &amp;lt;path&amp;gt;</code></td>
  <td>プログラム中で読み書きするファイルの場所を指定する</td>
</tr>
<tr>
  <td><code>--embed-file &amp;lt;path&amp;gt;</code></td>
  <td>プログラムに埋め込むファイルの場所を指定する</td>
</tr>
</tbody>
</table>

<p><code>-o</code>オプションを使うと出力するファイル名を指定だけでなく、ターゲットの変更もできます。
例えば.htmlで終わるファイル名を指定することで、HTMLを出力できます。</p>

<p></p><pre class="crayon-plain-tag">$ emcc -o hello.html hello.c
$ ls
hello.c		hello.html	hello.js</pre><p></p>

<p>出力されたHTMLファイルをブラウザで表示させると、次のように&#8221;Hello,world!&#8221;と出力されていることが確認できます。</p>

<p><img src="/wp-content/uploads/2017/02/helloworld-html-300x170.png" alt="ブラウザで実行されるHello, World" width="300" height="170" class="aligncenter size-medium wp-image-22505" srcset="/wp-content/uploads/2017/02/helloworld-html-300x170.png 300w, /wp-content/uploads/2017/02/helloworld-html.png 640w, /wp-content/uploads/2017/02/helloworld-html-207x117.png 207w" sizes="(max-width: 300px) 100vw, 300px" /></p>

<h2>ファイルも扱えます</h2>

<p>Node.js同様、C/C++のプログラムはファイルに対する操作が行えます。C/C++の標準的なライブラリで提供されている機能を利用してreadme.txtというファイルを読み込むプログラム実装すると、次のようになります。</p>

<p></p><pre class="crayon-plain-tag">#include 

int main(int argc, char** argv){
  FILE *file = fopen("readme.txt", "r");
  while(!feof(file)){
    char c = fgetc(file);
    if(c == EOF){
      break;
    }
    putchar(c);
  }
  fclose(file);
  return 0;
}</pre><p></p>

<p>このコードの中のfopen,feof,fgetc,fcloseがファイルアクセスに関する関数になります。これらの関数の呼び出しは同期的に行われます。このコードもEmscriptenで変換できますし、正しく動作します。</p>

<p>そもそもブラウザ内で動作するJSはファイルにアクセスできません。</p>

<p>また、このコードはファイルアクセスが同期的に処理されているため、そのまま変換を行うとアクセスが終わるまで、ブラウザの処理が止まってしまいます。下図のような仮想的なファイルシステムを提供することで、Emscriptenはこれらの問題を解決しています。</p>

<div id="attachment_22529" style="width: 310px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/02/emscripten-filesystem-architecture-300x178.png" alt="Emscripten で提供されるファイルシステム" width="300" height="178" class="aligncenter size-medium wp-image-22503" srcset="/wp-content/uploads/2017/02/emscripten-filesystem-architecture-300x178.png 300w, /wp-content/uploads/2017/02/emscripten-filesystem-architecture-207x123.png 207w, /wp-content/uploads/2017/02/emscripten-filesystem-architecture.png 619w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text"><a href="https://kripken.github.io/emscripten-site/docs/porting/files/file_systems_overview.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">File System Overview</a> より引用</p></div>

<p>まずSynchronous File System APIによって、同期的な関数呼び出しを非同期的なものに変換しています。</p>

<p>このAPIはファイルシステムの実装も隠蔽しています。通常はメモリ上に構築されるファイルシステムを利用しますが、コンパイル時のオプションによってNode.jsのファイルシステムや、IndexedDBを利用したものを利用できます。この切り替えを行ったとしても、コードを変更する必要はありません。</p>

<p>Emscriptenの仮想ファイルシステムはPOSIXのファイルシステムと同様に、デバイスファイルの作成や、ファイルシステムのマウントなどもサポートしています。</p>

<p>これらの機能は<a href="http://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.htm" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">FileSystem API</a> 経由で利用できます。標準入出力も自作のオブジェクトに置き換えられますので、なかなかに工夫しがいのあるかと思います。</p>

<h2>アセットを追加するには</h2>

<p>上記の例で利用したreadme.txtのようなアセットを利用するためには、Emscriptenによって提供される仮想ファイルシステムにアセットのファイルを追加する必要があります。</p>

<p>追加方法には、次の2つがあります。</p>

<p>ファイルサイズの大きいものや更新が頻繁なものは後者で、そうでないものは前者の方法を利用するとよいでしょう。</p>

<ul>
<li>利用するファイルをJSに埋め込む方法</li>
<li>利用されるファイルを1つにまとめ、それをXHRで読み込む方法</li>
</ul>

<p>前者は<code>--embed-file</code>オプションを、後者は<code>--preload-file</code>オプションをつけて<code>emcc</code>を実行することで、利用できます。</p>

<p>例えば先ほど紹介したプログラムはreadme.txtというファイルを読み込み、その内容を標準出力へと出力します。これを後者の方法で変換するには、次のように<code>emcc</code>コマンドを実行します。</p>

<p></p><pre class="crayon-plain-tag">$ emcc -o read-file.html --preload-file readme.txt read-file.c</pre><p></p>

<p>実行すると、HTMLファイルやJSファイル以外に<code>.data</code>ファイルが作成されます。</p>

<p>これはアセットを一つにまとめたものです。このファイルを非同期に読み込み、メモリ上に配置することで、Emscriptenはアセットのロードを実現させています。</p>

<div id="attachment_22529" style="width: 310px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/02/emscripten-reading-asset-300x170.png" alt="ファイルを読むコードの実行例" width="300" height="170" class="aligncenter size-medium wp-image-22504" srcset="/wp-content/uploads/2017/02/emscripten-reading-asset-300x170.png 300w, /wp-content/uploads/2017/02/emscripten-reading-asset.png 640w, /wp-content/uploads/2017/02/emscripten-reading-asset-207x117.png 207w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">文章は<a href="https://ja.wikipedia.org/wiki/Emscripten" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WikiPedia のEmscriptenの項目</a> より引用</p></div>

<h2>インライン JavaScript</h2>

<p>C/C++には、インラインアセンブラという機能があります。これはアセンブラで書かれたコードをソースコードの中に埋め込んでしまえる、というもので、高速化やシステムコールの実現などのために利用されます。</p>

<p>同様にEmscriptenでは、ソースコードの中にJavaScriptを埋め込めます。JavaScriptを埋め込むことで、C/C++のコードからブラウザの機能を利用できるようになります。</p>

<p>埋め込むためには<code>EM_ASM()</code>と呼ばれるマクロを使います。</p>

<p><code>alert</code>関数を呼び出すコードは、次のように書けます。</p>

<p></p><pre class="crayon-plain-tag">#include 

int main(){
  EM_ASM(
    alert("Hello, world!");
  );
  return 0;
}</pre><p></p>

<p>これを<code>emcc</code>でコンパイルして、実行した結果は次のようになります。</p>

<p><img src="/wp-content/uploads/2017/02/em-asm-300x171.png" alt="Cに埋め込まれたJavaScriptの実行例" width="300" height="171" class="aligncenter size-medium wp-image-22509" srcset="/wp-content/uploads/2017/02/em-asm-300x171.png 300w, /wp-content/uploads/2017/02/em-asm.png 640w, /wp-content/uploads/2017/02/em-asm-207x118.png 207w" sizes="(max-width: 300px) 100vw, 300px" /></p>

<p><code>EM_ASM_</code>を利用すれば、パラメーターを与えることもできます。<code>EM_ASM</code>との違いは、埋め込むJSのコードがブロックになっている点と、マクロの名前です。パラメータを与えるマクロは、末尾に<code>_</code>がついています。間違えがちなので注意が必要です。</p>

<p></p><pre class="crayon-plain-tag">#include 

int main(){
  EM_ASM_({
    alert(`Hello, world: ${$0}`);
  }, 100);
  return 0;
}</pre><p></p>

<p>与えられたパラメータは、<code>$0</code>,<code>$1</code>のように参照できます。上記の例では、与えられたパラメータをテンプレート文字列内で利用しています。</p>

<p>これらのマクロは<code>emscripten.h</code>に定義されています。詳しくは<a href="kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html" data-wpel-link="internal">ドキュメント</a>を参照してください。</p>

<h2>外部関数としてJavaScript関数を呼び出す</h2>

<p>マクロとしてJavaScriptを埋め込む以外に、C/C++からJavaScriptの関数を呼び出せます。それは外部関数として関数を宣言しておき、Emscriptenの<code>--js-library</code>オプションで実装を与える方法です。</p>

<p>次のコードでは、<code>zero</code>という関数を呼び出しています。この関数は外部の関数として宣言されています。、コンパイラは名前、引数の数と型、返り値の型以外わかっていません。</p>

<p></p><pre class="crayon-plain-tag">extern int zero();

int one(){
  return zero() + 1;
}</pre><p></p>

<p>通常のC/C++では、C/C++のコード（時にはコンパイル済みのバイナリ）として、この関数の実装は与えられますが、Emscriptenでは、これらに加えてJavaScriptでその実装を与えることもできます。</p>

<p>次のようにJavaScriptで<code>zero</code>を実装し、<code>LibraryManager</code>オブジェクトの<code>library</code>属性にマージしてやることで、C/C++のコードから呼び出せるようになります。</p>

<p></p><pre class="crayon-plain-tag">function zero(){
  return 0;
}

mergeInto(LibraryManager.library, {
  zero: zero
});</pre><p></p>

<h2>JavaScriptから変換されたコード利用するには</h2>

<p>基本的な機能はC/C++で実装済みで、それを操作するUIをWebで提供したい。そんな場合は、Emscriptenで変換されたC/C++のコードを、JSから呼び出すかたちで実装するとよいでしょう。</p>

<p>まず基本であるCで定義された関数をJSから呼び出してみましょう。次のような足し算を行う関数が、add.cというファイルに定義されていたとしましょう。</p>

<p></p><pre class="crayon-plain-tag">int add(int a, int b){
  return a + b;
}</pre><p></p>

<p>これを<code>emcc</code>コマンドでJSに変換します。</p>

<p></p><pre class="crayon-plain-tag">% emcc -o add.js -s "EXPORTED_FUNCTIONS=['_add']" add.c</pre><p></p>

<p><code>-s</code>オプションを使うと、コマンドラインオプションでは指定できない内部的なオプションを指定できます。</p>

<p>これを利用してJSへエキスポートする関数のリストである<code>EXPORTED_FUNCTIONS</code>を設定しています。このリストに載せる関数は、その名前の先頭に<code>_</code>をつけなければならないことに注意してください。</p>

<p>またC++の場合は、関数がマングリングされるの防ぐために、次のようにCのプログラムとして記述する必要があります。</p>

<p></p><pre class="crayon-plain-tag">extern "C"{
  int add(int a, int b){
    return a + b;
  }
}</pre><p></p>

<p>生成されたadd.jsをロードした後、次のようにJS側でasm.jsの関数をラップしたJavaScriptの関数を作成します。</p>

<p></p><pre class="crayon-plain-tag">const add = Module.cwrap("add", "number", ["number"]);</pre><p></p>

<p><code>Module</code>オブジェクトは、Emscriptenによって自動的に定義されるオブジェクトで、生成されたコードが実行されるときに、さまざまな形で利用されます。そのcwrapメソッドを使って、asm.jsの関数をJavaScriptから利用できるようにします。そのメソッドの引数はそれぞれ、ラップする関数の名前、返り値の型、引数の型を表します。</p>

<p>一度ラップされてしまえば、JavaScriptの関数と区別することなく利用できます。</p>

<p></p><pre class="crayon-plain-tag">const sum = add(1, 2); // 3
console.log(sum);</pre><p></p>

<p>C++で書かれたコードに対しては、上記の方法に加えて、C++で定義されたクラスをJavaScriptから利用できるようになります。これの詳細については述べませんが、手順を概観すると次のようになります：</p>

<ul>
<li>C++で定義されたクラスのためのWebIDLを作成する</li>
<li>作成したWebIDLを<code>tools/webidl_binder.py</code>で処理して、グルーコードを作成する</li>
<li>グルーコードとともに、cppファイルを<code>emcc</code>コマンドでコンパイルする</li>
</ul>

<p>上記の手順で処理することによって、C++で定義されたクラスを作成するコンストラクタが、<code>Module</code>オブジェクトの属性として参照できるようになります。</p>

<p>詳しくは<a href="http://kripken.github.io/emscripten-site/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.html#webidl-binder" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちらのドキュメント</a>を参照してください。</p>

<h2>まとめ</h2>

<p>手で書くのが大変なasm.jsも、CやC++で書いたコードをEmscriptenで変換することで簡単に生成できます。このとき標準ライブラリの変換も合わせて行われます。</p>

<p>またファイルシステムもEmscriptenによってエミュレートされるため、asm.jsへの変換を行う際にソースコードを変更する必要はほとんどありません。C/C++のコードをほとんど変えなくても、asm.jsへと変換できます。</p>

<p>またJavaScriptと変換されたコードの相互呼び出しも可能な上に、標準入出力もJSでエミューレートできます。そのおかげで、Emscriptenで作られたasm.jsコードと、JavaScriptで作られたコードとを柔軟に組み合わせてサイトやアプリを作ることができます。</p>

<p>これでめでたしめでたし、とならないのが技術の世界のつらいところです。Emscriptenによって作られたコードにも弱点があります。それはロードにかかる時間です。単なるHello Worldであっても、変換されたコードは300Kバイト程度になります。これは合わせて変換された標準ライブラリが、コードに含まれているためです。</p>

<p>コードのサイズは、Hello Worldなので300K程度で済んでいるともいえます。これがゲームともなれば、そのサイズはさらに増大します。コードサイズの大きさは、ダウンロードにかかる時間が大きいことも意味しますし、ダウンロード後、起動までの時間が長くなることも意味します。</p>

<table>
<thead>
<tr>
  <th>プログラム</th>
  <th>コードのサイズ（asm.js）</th>
  <th>コードのサイズ（WebAssembly）</th>
</tr>
</thead>
<tbody>
<tr>
  <td>Hello World</td>
  <td>301KiB</td>
  <td>204KiB</td>
</tr>
<tr>
  <td>AngryBots</td>
  <td>19MiB</td>
  <td>6MiB</td>
</tr>
<tr>
  <td>StandardAssets</td>
  <td>25.7MiB</td>
  <td>13.4MiB</td>
</tr>
<tr>
  <td>UnityChan-CRS</td>
  <td>21.3MiB</td>
  <td>11.4MiB</td>
</tr>
</tbody>
</table>

<p>この問題を解決するために、新しいファイルフォーマットの議論が始まりました。それがWebAssemblyです。</p>

<p>上の表をご覧いただければ、WebAssemblyを利用することでファイルサイズがぐっと小さくなっていることがわかるかと思います。最終回となる次回はWebAssemblyの役割と、その特徴について解説します。</p>
]]></content:encoded>
		
		<series:name><![CDATA[低水準言語asm.jsとWebAssembly詳解]]></series:name>
	</item>
	</channel>
</rss>
