入門!WebAssemblyを試してみた

こんにちは❗フリーランス・エンジニアの 九保すこひ です。

さてさて、このブログでは言語的にはPHPと並んでJavaScriptに関する記事も多く公開してきました。

というのも、JavaScriptは特にここ5年ほどで急速に発展し、人気を獲得しているからです。

ただ、JavaScriptでの処理が多くなってくると、たまに問題点が発生することもあります。

それは・・・

処理が遅くなる

という点です。

どうしてもブラウザでの処理は、ネイティブアプリと比べるとスピードで劣ってしまうのはよく知られていることです。

ただ、こんな状況を大きく変えるかもしれない技術があるのをご存知でしょうか。

それが今回テーマの・・・

WebAssembly(うぇぶあせんぶりー)

です。

そこで!

今回はWebAssemblyを使ってJavaScriptの処理を高速化する基本的な使い方をご紹介します。また、最後に「どれだけ処理が早くなっているか」を検証するために、WebAssemblyを使ったコードとJavaScriptだけのコードでスピードを比較してみたいと思います。

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境: Google Chrome 79

WebAssemblyとは?

WebAssemblyとは結局何かという話なんですが、簡単に言うと「処理が重い部分だけ高速なコードをつかっちゃおう!」という技術です。

車で言うと、最初と最後下道だけど、途中は高速道路を使ってビューン!って時間を短縮するイメージでしょうか。

(イメージ)

やりたいこと

今回はテストとして、「1〜300,000の数字の間に素数がいくつあるか」をカウントするコードを実装していきます。(なぜ中途半端な数字かというと、それ以上だと時間がかかりすぎてしまったからです。そのため、数字は皆さんのPC環境に合わせて変更してください)

WebAssemblyのファイル「.wasm」をつくる

WebAssemblyはC言語などのコードをコンパイルして使うことになりますが、最初は環境を構築するだけでゲンナリ・・・となってしまうと思うので、今回はオンライン上でコンパイルすることができるWasmFiddleというサービスを利用してやってみましょう。

このページを開くと、左側にC言語のコードを書いていく部分があるので、以下のコードを貼り付けてください。

#include <stdbool.h>

bool isPrime(num) {
  for(int i = 2; i < num; i++) {
    if(num % i == 0) return false;
  }
  return num > 1;
}

int countPrimeNumbers(maxNumber) {
  int count = 0;
  for(int i = 0; i < maxNumber; i++) {
    if(isPrime(i)) {
      count++;
    }
  }
  return count;
}

コードを貼り付けたら、ページ上部にある「Build」をクリックします。

ビルドが完了したらページ中程にある「Wasm」をクリックしてください。

すると、自動で「program.wasm」というファイルがダウンロードされます。これがWebAssemblyのコードになりますので、今回は「count_prime_numbers.wasm」という名前に変更してhttp://******/wasm/count_prime_numbers.wasmでアクセスできるようにサイトに設置します。

※ この例はLaravelを使った例ですので、ご自身の環境に合わせてファイルを設置してください。

WebAssemblyでコードをつくる

では、実際にブラウザからWebAssemblyを使ってみましょう。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<script>

    const maxNumber = 300000;

    fetch('/wasm/count_prime_numbers.wasm')
        .then(response => {

            return response.arrayBuffer();

        })
        .then(bytes => {

            return WebAssembly.instantiate(bytes);

        })
        .then(obj => {

            console.log('1 〜 '+ maxNumber +'にある素数の数は、'+ obj.instance.exports.countPrimeNumbers(maxNumber) +' 個');

        });

</script>
</body>
</html>

この中でやっていることは、まず先ほど用意したcount_prime_numbers.wasmfetch()を使ってAjaxでアクセスし、その内容を使ってWebAssemblyを起動、そして(WebAssembly内で)素数をカウントするという流れになっています。

JavaScript内での使い方は簡単かと思います。

スピードを比較してみる

では、次にWebAssemblyを使った場合と、JavaScriptだけで実行した場合はどれぐらい処理スピードが違うかを検証してみます。

まずはWebAssemblyを使った場合のコードです。(先ほどのコードに実行時間が分かるコードをつけ足しました)

/***  WebAssembly ***/

const maxNumber = 300000;
const startTime = performance.now();

fetch('/wasm/count_prime_numbers.wasm')
    .then(response => {

        return response.arrayBuffer();

    })
    .then(bytes => {

        return WebAssembly.instantiate(bytes);

    })
    .then(obj => {

        console.log('1 〜 '+ maxNumber +'にある素数の数は、'+ obj.instance.exports.countPrimeNumbers(maxNumber) +' 個');

        const endTime = performance.now();
        console.log('計算にかかった時間: '+ (endTime - startTime) +' ミリ秒');

    });

では、実行結果です。

約14秒かかってますね。

では、同じ内容をJavaScriptだけで実行してみましょう。
コードはこちらです。

/*** JavaScript ***/

const maxNumber = 300000;
const startTime = performance.now();

const isPrime = num => {

    for(let i = 2; i < num; i++) {

        if(num % i === 0) {

            return false;

        }

    }

    return (num > 1);

};

const countPrimeNumbers = maxNumber => {

    let count = 0;

    for(let i = 0; i < maxNumber; i++) {

        if(isPrime(i)) {

            count++;

        }

    }

    return count;

};

console.log('1 〜 '+ maxNumber +'にある素数の数は、'+ countPrimeNumbers(maxNumber) +' 個');

const endTime = performance.now();
console.log('計算にかかった時間: '+ (endTime - startTime) +' ミリ秒');

実行結果はこちら。

なんと、約23秒なので、さっきと比べると1.7倍ほどの時間がかかっています。
やはりWebAssemblyは高速ということになりますね。

いいですね😊✨

ちなみに:サポートしているブラウザ

2019.12.24現在、Can I useを見るとIE以外の主要なブラウザはほぼ全てWebAssemblyをサポートしています。

おわりに

ということで、今回は私も個人的に気になっていたWebAssemblyを試してみました。

なぜ注目していたかと言うと、もしVueReactなどがフルにWebAssembly化するとコードが早くなるだろうと考えていたからです。(それって技術的に可能かな??)

とにかく、もし皆さんのサイトにあるJavaScriptのスピードが遅い場合はWebAssemblyを使ってみるのもいいかもしれません。

ぜひ活用してくださいね。

ではでは〜!

今回の技術をつかった開発のご依頼、お待ちしております😊✨ お問い合わせ また、個人レッスンや、わかりにくい部分がありましたらからお気軽にご連絡ください。 どうぞよろしくお願いいたします!
このエントリーをはてなブックマークに追加       follow us in feedly