2017-11-15

「言語実装パターン」の LL(1) 再帰的下向き構文解析器を Rust で実装してみた

この記事は、「言語実装パターン」の LL(1) 再帰的下向き字句解析器を Rust で実装してみた の続きです。言語処理系の実装のセオリーと Rust を学ぶために、「言語実装パターン」で紹介されている各パターンを Rust で実装する活動の 2 回目です。

O'Reilly Japan - 言語実装パターン 言語実装パターン表紙

LL(1) 再帰的下向き構文解析器の実装

ここで作るのは、以下のような文法を持つ入力を受理するパーサです。

2017-11-12

「言語実装パターン」の LL(1) 再帰的下向き字句解析器を Rust で実装してみた

(2017-11-13 ちょっとコードに変更を加えたので加筆修正しました)

ごきげんよう。深夜のおかしな時間に起きてしまってついついケータイの公式アプリで Twitter を見てしまうとき、流速が遅いのについついリロードしてしまって、こんな感じになっちゃいますよね。もざみみです。

2017-11-08

AWS EC2 の新世代インスタンス c5 のマイクロベンチマーキング

2017-11-08 に、AWS の EC2 に新たなインスタンスファミリーである c5 シリーズが登場しました。これまでのコンピューティング最適化インスタンス c4 の後継となるものです。まだ ap-northeast-1 では利用できませんが、us-east-1 などのリージョンで利用することができます。

詳しい情報は以下の AWS の公式ページにまとまっています。

いろいろ新しくなった点はあるのですが、わたしが気になったのは以下のような点です。

2017-11-05

Redis の無停止マイグレーションと ElastiCache そして Redis Sentinel

やんごとなき事情により、CentOS 6 が動く古いサーバをつぶしていくというようなことを普段やっていて、Cent OS 6 上で動く Redis をどのように移行しようか、ということを最近考える機会があったので、このエントリにメモしておきます。

オンプレミスではなく AWS の EC2 や ElastiCache に寄せていくということと、Redis を利用するアプリケーションサーバでは Ruby on Rails が動いているという暗黙の前提があるため、そのつもりで読んでいただければと思います。

無停止で Redis サーバをマイグレーションすることの困難さ

Ubuntu 16.04 用に Redis サーバを準備するのはそれほど大変な作業ではありません。キャパシティプランニングさえ終えれば、あとはちょっと Itamae や Chef のレシピを書いてやるだけ、です。

2017-10-24

ISUCON 7 の予選を突破した (†空中庭園†《ガーデンプレイス》)

今年も大盛り上がりな ISUCON 7 でしたが、わたしも†空中庭園†《ガーデンプレイス》というチームで、同僚の @ryot_a_rai さんと @eagletmt さんと一緒に予選 (2 日目) に出場しました。

ISUCON7 本選出場者決定のお知らせ : ISUCON公式Blog にある通り、最終スコアは 588,107 でなんと両日合わせてのトップでした。身に余る光栄..! 自分用の記録も兼ねて、チームでどのように考えて動いたのかをメモしておきたいと思います。

📃 リポジトリ

リポジトリは @ryot_a_rai さんが公開してくれていますので、以下の GitHub リポジトリを覗いてみてください。

2017-10-14

max virtual memory areas vm.max_map_count [65530] is too low. で Elasticsearch が起動しないとき

Elasticsearch の起動時に、以下のようなログが出て起動できない場合があります。以下の例では、docker-compose を用いて Elasticsearch 5.5.2 を起動しています。

$ sudo docker-compose up es1
WARNING: The k9 variable is not set. Defaulting to a blank string.
Recreating dockercerebro_es1_1 ...
Recreating dockercerebro_es1_1 ... done
Attaching to dockercerebro_es1_1
es1_1      | [2017-10-14T07:56:08,786][INFO ][o.e.n.Node               ] [es1] initializing ...
es1_1      | [2017-10-14T07:56:08,880][INFO ][o.e.e.NodeEnvironment    ] [es1] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/vda2)]], net usable_space [80.9gb], net total_space [97.6gb], spins? [possibly], types [ext4]
es1_1      | [2017-10-14T07:56:08,881][INFO ][o.e.e.NodeEnvironment    ] [es1] heap size [990.7mb], compressed ordinary object pointers [true]
es1_1      | [2017-10-14T07:56:08,883][INFO ][o.e.n.Node               ] [es1] node name [es1], node ID [cmYYcTKrQa6LiHpCftbNKA]
es1_1      | [2017-10-14T07:56:08,883][INFO ][o.e.n.Node               ] [es1] version[5.5.2], pid[1], build[b2f0c09/2017-08-14T12:33:14.154Z], OS[Linux/4.13.5-1-ARCH/amd64], JVM[Oracle Corporation/OpenJDK 64-Bit Server VM/1.8.0_131/25.131-b11]
es1_1      | [2017-10-14T07:56:08,883][INFO ][o.e.n.Node               ] [es1] JVM arguments [-Xms2g, -Xmx2g, -XX:+UseConcMarkSweepGC, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -XX:+AlwaysPreTouch, -Xss1m, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -Djna.nosys=true, -Djdk.io.permissionsUseCanonicalPath=true, -Dio.netty.noUnsafe=true, -Dio.netty.noKeySetOptimization=true, -Dio.netty.recycler.maxCapacityPerThread=0, -Dlog4j.shutdownHookEnabled=false, -Dlog4j2.disable.jmx=true, -Dlog4j.skipJansi=true, -XX:+HeapDumpOnOutOfMemoryError, -Xms1g, -Xmx1g, -Des.path.home=/usr/share/elasticsearch]
es1_1      | [2017-10-14T07:56:09,997][INFO ][o.e.p.PluginsService     ] [es1] loaded module [aggs-matrix-stats]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [ingest-common]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [lang-expression]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [lang-groovy]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [lang-mustache]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [lang-painless]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [parent-join]
es1_1      | [2017-10-14T07:56:09,998][INFO ][o.e.p.PluginsService     ] [es1] loaded module [percolator]
es1_1      | [2017-10-14T07:56:09,999][INFO ][o.e.p.PluginsService     ] [es1] loaded module [reindex]
es1_1      | [2017-10-14T07:56:09,999][INFO ][o.e.p.PluginsService     ] [es1] loaded module [transport-netty3]
es1_1      | [2017-10-14T07:56:09,999][INFO ][o.e.p.PluginsService     ] [es1] loaded module [transport-netty4]
es1_1      | [2017-10-14T07:56:09,999][INFO ][o.e.p.PluginsService     ] [es1] no plugins loaded
es1_1      | [2017-10-14T07:56:11,788][INFO ][o.e.d.DiscoveryModule    ] [es1] using discovery type [zen]
es1_1      | [2017-10-14T07:56:12,544][INFO ][o.e.n.Node               ] [es1] initialized
es1_1      | [2017-10-14T07:56:12,545][INFO ][o.e.n.Node               ] [es1] starting ...
es1_1      | [2017-10-14T07:56:12,823][INFO ][o.e.t.TransportService   ] [es1] publish_address {172.19.0.2:9300}, bound_addresses {0.0.0.0:9300}
es1_1      | [2017-10-14T07:56:12,839][INFO ][o.e.b.BootstrapChecks    ] [es1] bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks
es1_1      | ERROR: [1] bootstrap checks failed
es1_1      | [1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
es1_1      | [2017-10-14T07:56:12,852][INFO ][o.e.n.Node               ] [es1] stopping ...
es1_1      | [2017-10-14T07:56:12,904][INFO ][o.e.n.Node               ] [es1] stopped
es1_1      | [2017-10-14T07:56:12,904][INFO ][o.e.n.Node               ] [es1] closing ...
es1_1      | [2017-10-14T07:56:12,925][INFO ][o.e.n.Node               ] [es1] closed
dockercerebro_es1_1 exited with code 78

環境

  • Arch Linux (2017-10-14 時点)
  • Docker version 17.09.0-ce, build afdb6d44a8
  • Elasticsearch 5.5.2
2017-10-07

Docker で唐突に MySQL 8.0 を試したくなったときにシュッと環境を用意するメモ

MySQL の運用をしていると、唐突に MySQL 8.0 を触りたくなる瞬間があると思います。

実際、わたしもたまに触りたくなって適当に Docker を使ってコンテナを起動して検証に使うことがあります。その都度ビルドするのも面倒なので.. いつもそのときに使うコマンドなどを忘れるので、メモがてらブログに置いておきます :rabbit:

環境

  • Arch Linux (2017-10-07 時点)
  • Docker version 17.09.0-ce, build afdb6d44a8
2017-06-03

Elasticsearch 5.x & Kibana 5 に移行したときになぜか棒が分割できない問題に対処したメモ

古いバージョンの EC2 上で動く Elasticsearch と Kibana を AWS Elasticsearch Service (5.1) & Kibana 5 に移行するときに、ちょっとハマったポイントがあったのでメモとして残しておきます。

一部のレコードがなぜか aggregate できない

MySQL が吐くスロークエリログをいい感じにしたいとき、fluent-plugin-mysqlslowquery を利用して Elasticsearch に送り、Kibana を使って視覚化する、という常套手段があります。 このとき、以下のスクリーンショットのような感じで Split Bars の Sub Aggregation に Temrs を指定し、スロークエリの SQL 文 (sql.keyword) で棒を分割するでしょう。

スロークエリログを解析するときのKibana のグラフの設定例
2017-05-07

Slack の発言を他のチャンネルに転送するためのツール「telescreen」

前々から作ろうと思いつつなかなか手が動かなかったのですが、ゴールデンウィークで暇を持て余してたこともあり、勢いで telescreen というツールを作りました。

mozamimy/telescreen

telescreen - A slack bot to forward messages by simple routing definition

telescreen は Slack の bot として常駐し、join しているチャンネルの発言を他のチャンネルに転送するためのツールです。人間の発言を集めたいというモチベーションで実装したため、bot による発言は転送しません。 利用には Bot integration で発行することのできる API トークンが必要になります。

2017-04-19

Rust でつくる VM 型の Brainf**k の処理系

これまで言語処理系のコンセプトこそ学んできたものの、実際に手を動かしてゼロから処理系を作る体験をしたことがなかったので、合間の時間を使ってガッと BF の処理系を作ってみました。 まず慣れている Ruby で実装して、その後、いま練習中の Rust で実装しました。この記事は、その記録になります。

実装の方針

BF は言語仕様が非常に小さいこともあり、初学者でも実装が簡単なため、ちょっとトリッキーな実装をしてみることにしました。 コードゴルフ的なアレではありません。完全に自己満足です。

  • やらなくてもなんとかなりそうだけど字句解析と構文解析をする
  • やらなくてもなんとかなりそうだけどコンパイラを作って仮想マシンの命令列にコンパイルする
  • やらなくてもなんとかなりそうだけどわざわざ仮想スタックマシンで動かす