paiza開発日誌

IT/Webエンジニア向け総合求人・学習サービス「paiza」(https://paiza.jp ギノ株式会社)の開発者が開発の事、プログラミングネタ、ITエンジニアの転職などについて書いています。

Rubyっぽいコードが爆速で動く!?CrystalとRubyを比較してみた

f:id:paiza:20180601114111p:plain
(English article is here)

f:id:paiza:20151217152725j:plainこんにちは、吉岡(@)です。

皆さんは、Crystalというプログラミング言語を知っていますか?

Rubyは、綺麗な構文のオブジェクト指向言語で、シンプルで短く素直なコードを書きやすいのが魅力ですが、速度は高速なわけではありません。

速度を求めるならC言語、Rust, Go言語といったコンパイル言語が強いですが、これらの言語はどうしてもコードの記述量が多くなったり、複雑になったりしがちです。

そこで、Rubyとコンパイル言語のいいところ取りをした言語がCrystalです。

Crystalは、Rubyに近い文法にもかかわらずコンパイルでき、コンパイル言語並みの速度で実行できます。

最近話題になっているので、名前ぐらいは知っている方も多いかと思いますが、実際に使った経験がある方は少ないのではないでしょうか?

新しい言語は、情報を読むだけではなく実際に手を動かして使ってみることで、より理解を深められます。…と言っても、ちょっと一つの言語を触ってみるために開発環境などをすべて用意するのは面倒ですよね。

CrystalはまだWindowsには対応していませんし、手順通りにインストールしたつもりでも、OSやバージョン、ほかのソフトウェアなど、さまざまな原因でエラーが出たりして失敗することもあります。

そこで、今回はブラウザだけでCrystalを使ったWeb開発ができるPaizaCloud Cloud IDEを使ってみます。

PaizaCloudは自由度が高く、さまざまなフレームワークや言語を使ったWeb開発が、初心者でも簡単にできますので、最短でCrystalを使った開発が始められます。開発環境がクラウド上で動作しているので、自分でサーバなどを用意しなくても、作ったWebサービスをその場で公開することも可能です!

今回は、CrystalとRubyで、簡単な計算をするプログラムと、基本的なWebアプリを作って動かします。また、CrystalとRubyでの速度の比較もしてみます。

手順に沿って進めれば、5分程度で試せると思いますのでぜひ挑戦してみてください。

PaizaCloud Cloud IDEを使う

それでは、始めていきましょう。

PaizaCloud Cloud IDEのサイトはこちらです。

https://paiza.cloud/

メールアドレスなどを入力して登録すると、登録確認メールが送られてきます。GitHubやGoogle(Gmail)ログインを利用すると、ボタン一つで登録することもできます。

サーバを作る

開発環境となるサーバを作りましょう。

f:id:paiza:20171213234155p:plain

「新規サーバ作成」ボタンを押して、サーバ作成画面を開きます。

インストール時にMySQLが動作している必要がありますので、MySQLをクリックして「新規サーバ作成」ボタンを押します。

f:id:paiza:20180228111202p:plain

3秒程度で開発環境がブラウザ上にできあがります。

f:id:paiza:20180228120822p:plain

Crystalのインストール

作成したPaizaCloud上のサーバに、最新のCrystalをインストールしてみましょう。

PaizaCloudでは、ブラウザ上でコマンドを入力するための「ターミナル」を使うことができます。

画面左側の「ターミナル」のボタンをクリックしましょう。

f:id:paiza:20171213234317p:plain

まず、Crystalのパッケージインストール時にはMySQLが動作している必要があるので、以下のコマンドで起動しておきます。

$ sudo systemctl enable mysql
$ sudo systemctl start mysql

続いて、Crystalのパッケージをインストールします。

$ curl https://dist.crystal-lang.org/apt/setup.sh | sudo bash
$ sudo apt-get install crystal

以上で準備ができました!

Crystalを使ってみる

まず、文字を表示してみましょう。まず、"hello.cr"という名前のファイルを作成しましょう。Crystalのプログラムは、通常".cr"という拡張子を使います。

PaizaCloudの左側の「新規ファイル」ボタンをクリックするか、ファイル管理ビューの右クリックメニューから"新規ファイル"を選択します。

f:id:paiza:20171218232330p:plain

ファイル作成ダイアログが表示されるので、"hello.cr"と名前を入れて「作成」ボタンを押します。

f:id:paiza:20180601112055p:plain

"hello.cr"ファイルが開きますので、以下のようにCrystalのコードを書きましょう。Crystalの文法はほぼRubyと同じですから、Rubyに近い感覚でコーディングできます。

hello.cr:

puts "Hello world!"

f:id:paiza:20180601112352p:plain

編集できたら、「保存」ボタンまたはCtrl-S(Command-S)で保存します。

作成したプログラムを実行するには、crystalコマンドを使います。

$ crystal hello.cr

f:id:paiza:20180601112508p:plain

"Hello world!"と表示され、Crystalでプログラムが正常に実行できました!

Crystalでは、このように直接プログラムを実行できますが、"crystal build ファイル名 --release"で一度コンパイルして、実行ファイルを作成してから実行することもできます。

"--release"オプションを付けないと最適化がされず、「高速に動作する」というCrystalの利点が活かせませんので、忘れずに付けておきましょう。

$ crystal build hello.cr --release
$ ./hello

f:id:paiza:20180601112607p:plain

CrystalとRubyで円周率を計算してみる

次に、CrystalとRubyで円周率を計算して、計算速度やメモリ使用量を比べてみましょう。

以下のようなプログラムを作成してみます。

pi.cr:

def pi(n)
  count = 0
  n.times do
    x=rand; y=rand
    if x*x + y*y < 1
      count += 1
    end
  end
  return count.to_f / (n/4)
end

puts pi(10000000)

今回は、モンテカルロ法で計算してみます。

モンテカルロ法では、1x1の正方形の中にランダムに点を作り、円の中に入る点の数を数えます。ランダムな点の数を増やせば増やすほど計算精度が上がります。今回は、1000万個の点を作ってみましょう。

このコードはRubyのコードで、RubyでもCrystalでも動作します。

まずはRubyで実行してみましょう。

~$ time ruby pi.cr
3.1417268

real    0m2.553s
user    0m2.491s
sys     0m0.059s

円周率が表示されました。約2.6秒かかっていますね。

次に、Crystalで実行してみましょう。まずはコンパイルします。

$ crystal build pi.cr --release

実行ファイル"pi"が作成されました。

それでは実行してみましょう。

$ time ./pi
3.1423996

real    0m0.265s
user    0m0.262s
sys     0m0.002s

同じく円周率が計算できましたが、今度はわずか0.27秒で、約10倍速くなっています!すごいですね!

メモリ使用量も比べてみましょう。

まずはRubyです。

$ /usr/bin/time -v ruby pi.cr 
...
        Maximum resident set size (kbytes): 8984
...

約8MBのメモリを利用していますね。

今度はCrystalです。

$ /usr/bin/time -v ./pi
...
        Maximum resident set size (kbytes): 2820
...

わずか2.8MBと、Rubyの30%ほどのメモリで動作しています!

CrystalとRubyでWebサービスを動かしてみる

次に、簡単なWebサービスを作って動かして、性能を比べてみましょう。

まずは、RubyのシンプルなWebアプリケーションフレームSinatraを使って、Webサービスを作って動かします。

以下のような"Hello Sinatra!"と表示するサービスを作成します。

sinatra_app.rb:

require 'sinatra'

get '/' do
  'Hello Sinatra!'
end

動かしてみましょう。ターミナルから"ruby sinatra_app.rb"と実行します。

$ ruby sinatra_app.rb

SinatraのWebサーバが動作しました。Sinatraはデフォルトで4567番ポートでサーバが動作します。

サーバが動作すると、PaizaCloudの画面左に、"4567"と書かれたブラウザアイコンが表示されます。

アイコンをクリックすると、PaizaCloud上でブラウザが起動します。

ここでは、Sinatraのプログラムが作成した"Hello Sinatra!"とメッセージが表示されました。

次に、Crystalで動作する、Sinatra風のWebアプリケーションフレームワークKemalでWebサービスを作成します。

まずは、Crystalのプロジェクト"crystal init app アプリケーション名"で作成します。

$ crystal init app crystal_app

crystal_appというディレクトリが作成されました。このディレクトリの中に、shard.ymlというファイルが作成されます。

CrystalではRubyのgemのようなパッケージ管理ツールshardが利用できます。ここでは、karmaパッケージを利用するので、shard.ymlファイルにパッケージを記述しましょう。

crystal_app/shard.yml:

dependencies:
  kemal:
    github: kemalcr/kemal

そして、"shards install"コマンドでパッケージをインストールします。

$ cd crystal_app
$ shards install

"src/crystal_app.cr"というファイルが作成されていますから、以下のように変更して、"Hello Crystal!"というメッセージを表示するWebサービスを作成します。

crystal_app/src/crystal_app.cr:

require "kemal"

get "/" do
  "Hello Crystal!"
end

Kemal.run

コード自体は、Sinatraで作ったときとほとんど同じですね。

それでは、コンパイルして実行してみましょう。

$ cd ~/crystal_app
$ crystal build src/crystal_app.cr --release
$ ./crystal_app

CrystalのWebサーバが動作しました!

Crystalはデフォルトで3000番ポートでサーバが動作します。

サーバが動作すると、PaizaCloudの画面左に、"3000"と書かれたブラウザアイコンが表示されます。

アイコンをクリックすると、PaizaCloud上でブラウザが起動します。

ここでは、Crystalのプログラムが作成した"Hello Crystal!"とメッセージが表示されました。

それでは、作成したRuby(Sinatra)と、Crystal(Kemal)の性能を比べてみましょう。

性能比較には"ab"コマンドを使ってみます。

まずはRuby(sinatra)の性能を測ります。

以下のコマンドでは、KeepAliveを有効にして10並列で3000リクエストを送っています。

$ time ab -k -c 10 -n 3000 http://127.0.0.1:4567/
...
real    0m1.583s
...

約1.6秒かかっています。

次に、Crystal(Kemal)の性能を測ります。

$ time ab -k -c 10 -n 3000 http://127.0.0.1:3000/
...
real    0m0.362s
...

わずか0.36秒ということで、Ruby(Sinatra)より4倍以上速くなっていますね!

メモリ使用量も比べてみましょう。 Ruby(Sinatra)とCrystal(Kemal)を/usr/bin/time -vコマンドで起動し、先ほどのabコマンドを実行したあとCtrl-Cで終了し、メモリ使用量を見てみましょう。

まずはRuby(Sinatra)です。

$ /usr/bin/time -v ruby sinatra_app.rb
...
Ctrl-C
...
        Maximum resident set size (kbytes): 22128
...

約22MBですね。

次にCrystal(Kemal)です。

$ /usr/bin/time -v ./crystal_app
...
        Maximum resident set size (kbytes): 6992
...

わずか約7MBで、1/3程度のメモリ使用量となっています!

まとめ

というわけで、CrystalとRubyを使った円周率測定とWebサービスをPaizaCloud上で作成し、比較してみました。

円周率測定ではCrystalの方が10倍程度、Webサービスでも4倍程度速くなっていましたね。両方ともメモリ使用量も1/3以下になっていたので、Crystalが非常に高速かつ軽量に動作することがわかりました。高速に動くコードを簡潔に書きたい場合などに適しているかと思います。

また、今回はPaizaCloudを使って、開発環境などを用意しなくても簡単に試すことができました。Crystalのような新しいプログラミング言語は、実際に使ってみてわかることや学べることも多いので、ぜひいろいろ試してみてください。


PaizaCloud」は、環境構築に悩まされることなく、ブラウザだけで簡単にウェブサービスやサーバアプリケーションの開発や公開ができます。 https://paiza.cloud


paizaラーニング」では、未経験者でもブラウザさえあれば、今すぐプログラミングの基礎が動画で学べるレッスンを多数公開しております。

そして、paizaでは、Webサービス開発企業などで求められるコーディング力や、テストケースを想定する力などが問われるプログラミングスキルチェック問題も提供しています。

スキルチェックに挑戦した人は、その結果によってS・A・B・C・D・Eの6段階のランクを取得できます。必要なスキルランクを取得すれば、書類選考なしで企業の求人に応募することも可能です。「自分のプログラミングスキルを客観的に知りたい」「スキルを使って転職したい」という方は、ぜひチャレンジしてみてください。

paizaのスキルチェック





※このブログで紹介しているキャンペーンやイベント、およびサイト内の情報については、すべて記事公開時の情報となります。閲覧されたタイミングによっては状況が変わっている場合もございますのでご了承ください。

ITプログラマー・エンジニア転職・就活・学習のpaiza

プログラミング入門講座|paizaラーニング

PHP入門編Ruby入門編Python入門編Java入門編JavaScript入門編C言語入門編C#入門編アルゴリズム入門編

エンジニアのためのプログラミング転職サイト|paiza転職

プログラミング スキルチェックエンジニア求人一覧

未経験からエンジニアを目指す人の転職サイト|EN:TRY

プログラミング スキルチェックエンジニア未経験可求人一覧

エンジニアを目指す学生の就活サイト|paiza新卒

プログラミング スキルチェックエンジニア求人一覧

ブラウザを開くだけで エディタ、Webサーバ、DB等の開発環境が整う|PaizaCloud