risou's Lithograph

Lithograph を育てる

2019-09-20

毎日ブログを書くような性格でもないのだが、前回の記事から今日までの間、隙を見つけては Lithograph を育てていた。
育てるといってもたいしたことはしていない。
(実はバージョンを上げてすらいない)

改善内容は以下。

  • Travis CI での build の実行結果を Slack に通知するサンプルを追加
  • Google Analytics のタグを埋め込めるようにした
  • OGP 用のタグを設定できるようにした
  • build 用のシェルに -eu を設定

だいたいこれくらい。
自分で使っているうちに、「あれもできたらな」と思ったものに対応していっている感じだ。

他にも改善したいことはあるが、これはたぶんすぐにはやらないだろうな、というものもある。
例えば、

  • 初期セットアップ時に生成するリソースファイルのみ更新するコマンドの追加
    • Lithograph 本体側で設定ファイル等に更新があった場合に反映したい
  • config.yml に必要な項目が揃っているかをチェックする機能
    • あると良いかもだけど、今は必須項目もほぼないのでなくてもいいかな
  • 既にファイルのあるディレクトリでの初期セットアップを抑制する機能

あたり。これらはあると便利そうな気がするけど、あんまり頻繁に使われるものではないので実装を急いでいない。

時間さえ見つけられれば(他に優先度の高いものがなければ)やりたいのは主に build 周りの改良で、

  • 「次の記事」「前の記事」へのリンクを付けられるようにする
  • 記事にタグを付けられるようにして、タグでフィルタしたリストページを作る
  • 更新のない記事の build をスキップする

などは後々のことを考えるとやっておきたい。

けれど、他にもやるべきことがあったりするので、これらはまたそのうち時間を見つけて、といった感じ。

builderscon 2019 の記録

2019-09-10

もう1週間以上前1のことだけど、今年も行ってきたので自分のためにログを残しておく。
といっても写真は全然撮ってないし、ボリューム厚めのログは勤め先の情報共有ツールの方に書いたので、こちらには軽く書くだけ。

builderscon 2019

去年の記事

会場

去年と異なり、北千住の東京電機大学。
北千住自体は初めてではないけど、実は駅周辺のこととかあまり知らなかったので、雰囲気が知れてよかった。

ちなみに運営の心遣いのレベルが高く、最寄り駅から会場への経路を ブログで詳しく解説 してくれているが、僕は見逃して普通に迷ったりしました。

チケット

今回は コンプリートパック なるものがあり、これを買っておくと後々別途チケットが販売される懇親会等のチケットを購入する必要がなくなるということで、バーンと買っちゃいました。
もちろん全部入りだけあって相応に高額であり即決できるほどではなかったのですが、面倒なことは苦手なので「用意されてるチケット数少ないし、売り切れる前に……」と買ってしまった、という流れです

トーク

前夜祭や LT を除けば、だいたいどの時間帯も複数のトークが並行して行われており、今回だと最大5並列くらいだった気がする。
それだけあれば、聞きたいトークが2つないし3つくらいはかぶるもので、毎時間「どれ聞きに行こう……」ってなりました(贅沢な悩み)。

ひとつひとつに言及すると長くなってしまうので、これはすごかったなというのを上げると、

  • スーパーカミオカンデ
  • RDB のトラブル
  • Oxygen Not Included

あたりはとても印象に残った。また、聞けなくて悲しい思いをしたトークもいくつもあり、特にサイバー攻撃日誌は聞きに行きたかった。

builderscon は後日各トークの録画が公開されるはずなので、それを楽しみに待つ次第。

スポンサード

今の勤め先では、いくつかのカンファレンスにスポンサードしており、 builderscon にスポンサードすることも不可能ではなさそうな気がしている。
とはいえむやみにカンファレンスにスポンサードしても勤め先にメリットがなければ意味がないので、そこを考慮してスポンサードを打診していない。
でも勤め先の同僚が参加して得るものがないとは全く思わないので、同僚たちがもっと参加してくれると嬉しいなあ、と思う。


  1. 1つ前の記事 の ISUCON よりも前のイベント。順番がおかしい。

ISUCON 9 予選惨敗記録

2019-09-09

惨敗した。

当日のログもあまり残せておらず、記憶がすぐに劣化してしまいそうなので乱文になるかもしれないがここに記録しておく。

参加のきっかけ

社内の Slack で「興味ありそうな人がいれば出たい」という趣旨の発言をしたところ、反応があったのでさっとチームを組んで参加することにした。
3人での参加だったが、当然この組み合わせは初だった(もっというと僕以外の2人は ISUCON 自体初参加だった)。

当日までの準備

仕事が忙しかったことを主な言い訳にするが、3人揃って時間を確保して過去問を解く、といったことはできなかった。

何度か集まって話をする時間を設けることができ、そこで序盤の進め方や役割分担について話をしておいた。
また、提示された環境で(インフラ担当の方に)インスタンスを立ててもらって鍵認証で SSH 接続できること、などは確認しておいた。
当然だが、この時点で言語も選択していた。会社で使っているということもあり Ruby を選択した。

当日の動き

集合〜セットアップ

同僚との参加だったので必然的にオフィスに集まることになった。
休日はビルの施錠周りにややこしい部分があり、経験豊富な僕が解錠する役を請け負った1

実は我々以外にもう1チーム、同じオフィスを利用するチーム2がおり、そちらの皆さんのためにもあまり遅くならないようにオフィスを開ける必要があった。

余裕をもって 8:30 頃に出社し、同じオフィスで参加する皆を迎え入れた。
並行して3人が近い席で作業できるようにディスプレイやキーボードなどをセットアップしたり、ホワイトボード、会議用モニタ + Apple TV を座席近くに集めた。

時間的には結構余裕を残して準備を終えられたと思う。

開始〜昼頃

開始してすぐに、インフラを担当してくれる方にインスタンスを立ててもらったり、鍵を配備してもらったりして、準備が整ったらまずは一度ベンチマークを走らせてもらった。

並行してもう1人の同僚が初期コードを Git で管理管理できるようにしたりデプロイ周りを整えてくれたりした。

僕はドキュメントを読み漁ったり、コードを軽く読んだりした。

ベンチマークの結果が出たあたりで一度コミュニケーションを取り、各々の初手を相談して動きを決めた。

この時間帯は MySQL のスロークエリを探して、インデックスを張ったりしていたと思う。
並行して alp での計測結果をもとに /users/transactions.json の実装を調べたりしていたはずだ。

結局、昼過ぎの時点ではスコアに全く影響を与えることができなかった。

昼過ぎ〜夕方

正直、記憶がだいぶ曖昧で何をしていたか覚えていない。

Job を見る限りでは14時台に何度かベンチマークを実行し、 /initialize で fail したりしていたようだ。
おそらく app と db でインスタンスを分けて、別インスタンス上の DB に接続しにいくあたりで環境変数に 127.0.0.1 が入ってしまってうまくいかないとか、そういうことをやっていた気がする。
あとログ出したいよね、という話をしていた記憶があるのでそのあたりを頑張っていたような……。

15時台になると success するようになり、ベンチマークの結果が若干上にブレたり下にブレたりしていた様子(しかし例によって記憶がない)。

夕方〜終了

最終的に MySQL のスロークエリが SELECT * FROM categories ばかりになったので、「これ変更されないマスタデータだし、起動時に全部取得してキャッシュしようぜ」って考えてシュッと実装した。

WHERE parent_id = ? のところはインデックスを張っていたのでスルーしたのと、 /settings でカテゴリのリストを取得している箇所も(そのまま出力しているのが気になったので)そのままにしておいた。

このキャッシングは若干の効果があったようでチームとしてはここで初めて初期スコアを脱出した感じになった。

その後、 /users/transactions.json のクエリ発行周りをいじって動かしてみたり SELECT * なクエリのカラムを指定する形に変更してみたりしたが、時間があまり残っていなかったこともあり、スコアが変わらなかったりベンチマークが fail してしまう変更は結局取り込まなかった。

終盤になると、3台構成のインスタンスを app 2台、 db 1台にして app をバランシングしようとしていたが、画像アップロードの問題があり苦戦したあげく、バランシングした方がスコアが落ちてしまったので、これもやめた(結局最後まで app 1台、 db 1台で進めた)。

また、序盤から存在が気になっていた campaign という項目の値を変化させてベンチマークを一通り動かしてみた。この項目には 0〜4 の整数が入り得ることがわかっており、5パターンのベンチマークを試して、最もスコアが出る値を入れることにした。
(このタイミングの変更としては、これが一番スコアに貢献した)

最後に仕込んでいたログを消したり、再起動してもベンチマーク通ることを確認したりして終了時間を迎えた。

雑感

問題

とても良い、そして難しい問題だったように思う。
スコアを上げるためには、ちゃんとシステムがやりたいこととやっていることを理解することが必要だったのではないだろうか。
セオリー通りにこれをやっておけばとりあえずスコアが上がる、という簡単さはあまり感じられなかった。

進め方

色々と反省はある。

  • 練習不足が如実に出て、序盤の立ち上がりが遅かった
  • デプロイ用にシェル書いてもらったりしたけど、ほとんど使わなかった
  • バージョン管理していたけど、インスタンス上でコードいじったりもした
    • バージョン管理の目的はローカルでのコード編集だけではないので、バージョン管理をしたのは良かった
  • campaign の値変更はもっと早めに一度試しておくべきだった
    • 値によって何が変わるのかの把握が遅かった
  • 実装の読み込みが浅かった
  • ホワイトボード、 Apple TV を活かせなかった

一方で良かったな、と思うこともある。

  • 初参加(初組み合わせ)にしてはよく動けたと思う
  • 役割分担が自然にできた
  • インスタンス利用やベンチマーク実施を相談しながら進められた
  • その時々で、誰が何をやるかの認識合わせができた
  • 終盤、戻しの判断が安全で安心感があった
    • 駆け込みベンチマークでヒヤヒヤしたり、終盤で0点に怯えたりせずに済んだ
    • 業務ではないのでもう少しチャレンジしても良かったとは思う

まとめると 実力不足を感じつつも、まだまだやれそうな気配もあり、悔しい思いをした といったところ。

心が折れて次回参加する流れにならないことが最も懸念していた展開だったので、チームの誰も心が折れず、リベンジの意欲を高く持って終わりを迎えられたので、それは本当に良かった。


  1. 正直これが一番の大仕事だったと思っている。

  2. このチームの1人が同僚であり、ちゃんと会社の許可を得て利用している。

ブログシステムを一新した

2019-09-06

先日、社内 LT でブログ更新してないネタを使ったので、晴れて更新できるようになった。

ということで、ブログのシステムを新しくした。
見た目はもちろんだけどシステム自体も新規に作り直した。

前作は Haskell 製だったが、今作は Perl 6 製。
(とはいえ、どちらもブログシステム、というには圧倒的に機能が少ない。個人的に必要なものしか実装していないからだ)

今作には Lithograph という名前をつけた。

なぜ Perl 6 を使ったか

完全に趣味。
静的サイトジェネレータを作ろうと思ったとき、「それなら Perl 6 でもできそうだな」と思ったのが大きい。
日々のタスクが少なくない中でいつやるかというと、だいたい帰省したときで、2018年の年末〜2019年正月あたりで作り始めたが完成させられず2019年夏の完成となった。

なぜ Lithograph という名前にしたか

静的サイトジェネレータにしたのも同じ理由だが、コンテンツとしてより長く生き長らえてほしいと思ったとき、いわゆる動的なブログシステムよりも静的サイトジェネレータを使って HTML を出力しておく方が良さそうだと思ったからだ。
その発想に至る経緯で、「紙は便利だけど、石版に彫った方が当然長い年月を超えられる」ということに着目し、「僕が今欲しているのは、 Web における石版だな」と思ったことによる。
(機会があればいつかどこかでこの思いを整理したい)

見た目の話

去年くらいに Electron アプリ作ってたときくらいに簡単で良いなと思った Bulma を使った。
とはいえ、見た目の部分は利用者がそれぞれ好きにすれば良いことなので、このシステムが推奨するものではない。
とりあえず僕以外に使う人はいないだろうという想定で僕が使いたいものを使った。

というわりに、見た目を変える方法を含むカスタマイズ方法をどこにも記載していないので、そのうちドキュメントをちゃんと書かないといけない。

Perl 6 にして苦労はなかったか

これは当然いろいろあって、どこかで共有することもあるかもしれない。
いくつか概要を書いておくと、

  • RakudoStar2019.07 にすると zef install YAMLish が失敗する
  • Perl 6 で大量の markdown ファイルをパースして HTML として保存していると途中で解放済みメモリを解放しようとして死ぬ
    • MoarVM になにか問題があるのか僕の Perl 6 の実装が良くないのか
    • 結局どうしようもなくて最後に shell に頼った
  • IO::Psth に相対パスを与えてディレクトリを登っていこうとするとおかしなパスが生成される
  • 仕組み上 Travis CI を使って markdown を HTML にパースできるようにしているが、この処理の際に不定期に zef install に失敗して死ぬ

といったつらみがあった。

このあたりは時間があればもう少し深堀りしてみたい。
といいつつ、次に触る時間を得たときにはバージョンが上がって解消している可能性もある(それは当然大歓迎です)。

[追記 2019-09-09]
ちなみに Perl 6 製の静的サイトジェネレータを使ってみたいなら、オススメは Uzu だ。

alacritty で Emacs を使う

2019-05-13

alacritty というターミナルエミュレータが速いという話を聞き、仕事が一段落したタイミングで導入してみた。

alacritty

まだまだ実装段階というかリッチな機能が不足していてつらいという話を聞いたりもするが(タブで複数開けないとか)、個人的には今のところ使っていくのに最低限必要なものは揃ってくれていると感じた。

僕が使っていくのに困らない大きな要因は tmux を愛用しているから、というのが大きそうではある。
tmux でタブや分割に相当する機能が確立されているため、ターミナルエミュレータ側での実装を必要としていない。

alacritty で Emacs を使う

本題。

Mac OS 上で試してみたところ、いくつかの問題が起きた。

Meta キーが反応しない

Mac OS で Emacs を使うにあたっては option/alt キーを Meta として扱うように設定しているが、これまで使っていた iTerm2 では設定できたこれが alacritty では今はまだ設定できない。

これにどう対応するかというと、以下のような設定を追加する。 以下の設定は Set option as meta in MacOS · Issue #62 · jwilm/alacritty から拝借した。

key_bindings:
  # meta
  - { key: A,         mods: Alt,       chars: "\x1ba"                       }
  - { key: B,         mods: Alt,       chars: "\x1bb"                       }
  - { key: C,         mods: Alt,       chars: "\x1bc"                       }
  - { key: D,         mods: Alt,       chars: "\x1bd"                       }
  - { key: E,         mods: Alt,       chars: "\x1be"                       }
  - { key: F,         mods: Alt,       chars: "\x1bf"                       }
  - { key: G,         mods: Alt,       chars: "\x1bg"                       }
  - { key: H,         mods: Alt,       chars: "\x1bh"                       }
  - { key: I,         mods: Alt,       chars: "\x1bi"                       }
  - { key: J,         mods: Alt,       chars: "\x1bj"                       }
  - { key: K,         mods: Alt,       chars: "\x1bk"                       }
  - { key: L,         mods: Alt,       chars: "\x1bl"                       }
  - { key: M,         mods: Alt,       chars: "\x1bm"                       }
  - { key: N,         mods: Alt,       chars: "\x1bn"                       }
  - { key: O,         mods: Alt,       chars: "\x1bo"                       }
  - { key: P,         mods: Alt,       chars: "\x1bp"                       }
  - { key: Q,         mods: Alt,       chars: "\x1bq"                       }
  - { key: R,         mods: Alt,       chars: "\x1br"                       }
  - { key: S,         mods: Alt,       chars: "\x1bs"                       }
  - { key: T,         mods: Alt,       chars: "\x1bt"                       }
  - { key: U,         mods: Alt,       chars: "\x1bu"                       }
  - { key: V,         mods: Alt,       chars: "\x1bv"                       }
  - { key: W,         mods: Alt,       chars: "\x1bw"                       }
  - { key: X,         mods: Alt,       chars: "\x1bx"                       }
  - { key: Y,         mods: Alt,       chars: "\x1by"                       }
  - { key: Z,         mods: Alt,       chars: "\x1bz"                       }
  - { key: A,         mods: Alt|Shift, chars: "\x1bA"                       }
  - { key: B,         mods: Alt|Shift, chars: "\x1bB"                       }
  - { key: C,         mods: Alt|Shift, chars: "\x1bC"                       }
  - { key: D,         mods: Alt|Shift, chars: "\x1bD"                       }
  - { key: E,         mods: Alt|Shift, chars: "\x1bE"                       }
  - { key: F,         mods: Alt|Shift, chars: "\x1bF"                       }
  - { key: G,         mods: Alt|Shift, chars: "\x1bG"                       }
  - { key: H,         mods: Alt|Shift, chars: "\x1bH"                       }
  - { key: I,         mods: Alt|Shift, chars: "\x1bI"                       }
  - { key: J,         mods: Alt|Shift, chars: "\x1bJ"                       }
  - { key: K,         mods: Alt|Shift, chars: "\x1bK"                       }
  - { key: L,         mods: Alt|Shift, chars: "\x1bL"                       }
  - { key: M,         mods: Alt|Shift, chars: "\x1bM"                       }
  - { key: N,         mods: Alt|Shift, chars: "\x1bN"                       }
  - { key: O,         mods: Alt|Shift, chars: "\x1bO"                       }
  - { key: P,         mods: Alt|Shift, chars: "\x1bP"                       }
  - { key: Q,         mods: Alt|Shift, chars: "\x1bQ"                       }
  - { key: R,         mods: Alt|Shift, chars: "\x1bR"                       }
  - { key: S,         mods: Alt|Shift, chars: "\x1bS"                       }
  - { key: T,         mods: Alt|Shift, chars: "\x1bT"                       }
  - { key: U,         mods: Alt|Shift, chars: "\x1bU"                       }
  - { key: V,         mods: Alt|Shift, chars: "\x1bV"                       }
  - { key: W,         mods: Alt|Shift, chars: "\x1bW"                       }
  - { key: X,         mods: Alt|Shift, chars: "\x1bX"                       }
  - { key: Y,         mods: Alt|Shift, chars: "\x1bY"                       }
  - { key: Z,         mods: Alt|Shift, chars: "\x1bZ"                       }
  - { key: Key1,      mods: Alt,       chars: "\x1b1"                       }
  - { key: Key2,      mods: Alt,       chars: "\x1b2"                       }
  - { key: Key3,      mods: Alt,       chars: "\x1b3"                       }
  - { key: Key4,      mods: Alt,       chars: "\x1b4"                       }
  - { key: Key5,      mods: Alt,       chars: "\x1b5"                       }
  - { key: Key6,      mods: Alt,       chars: "\x1b6"                       }
  - { key: Key7,      mods: Alt,       chars: "\x1b7"                       }
  - { key: Key8,      mods: Alt,       chars: "\x1b8"                       }
  - { key: Key9,      mods: Alt,       chars: "\x1b9"                       }
  - { key: Key0,      mods: Alt,       chars: "\x1b0"                       }
  - { key: Space,     mods: Control,   chars: "\x00"                        } # Ctrl + Space
  - { key: Grave,     mods: Alt,       chars: "\x1b`"                       } # Alt + `
  - { key: Grave,     mods: Alt|Shift, chars: "\x1b~"                       } # Alt + ~
  - { key: Period,    mods: Alt,       chars: "\x1b."                       } # Alt + .
  - { key: Key8,      mods: Alt|Shift, chars: "\x1b*"                       } # Alt + *
  - { key: Key3,      mods: Alt|Shift, chars: "\x1b#"                       } # Alt + #
  - { key: Period,    mods: Alt|Shift, chars: "\x1b>"                       } # Alt + >
  - { key: Comma,     mods: Alt|Shift, chars: "\x1b<"                       } # Alt + <
  - { key: Minus,     mods: Alt|Shift, chars: "\x1b_"                       } # Alt + _
  - { key: Key5,      mods: Alt|Shift, chars: "\x1b%"                       } # Alt + %
  - { key: Key6,      mods: Alt|Shift, chars: "\x1b^"                       } # Alt + ^
  - { key: Backslash, mods: Alt,       chars: "\x1b\\"                      } # Alt + \
  - { key: Backslash, mods: Alt|Shift, chars: "\x1b|"                       } # Alt + |

Ctrl/Alt + 記号の一部が反応しない

上記の他に、僕が Emacs 上で設定しているホットキーが一部反応しなかったのでそれについても設定を加えている。

  - { key: Semicolon, mods: Control,   chars: "\x18\x40\x63\x3b"            } # Ctrl + ;
  - { key: Semicolon, mods: Alt,       chars: "\x1b;"                       } # Alt + ;
  - { key: Slash,     mods: Control,   chars: "\x1f"                        } # Ctrl + /
  - { key: Apostrophe, mods: Control,  chars: "\x18\x40\x63\x27"            } # Ctrl + ''

それぞれ helm-mini, comment-dwim-2, undo-tree-undo, redo を割り当てていたが、この設定を追加しておかないと反応しなかった。

その他のカスタマイズ

本題は以上だが、その他にいくつか不便を解消するために行った設定があるので残しておく。

日本語を表示するためのフォントの設定

これまで Menlo for Powerline を使っていたが、 El Capitan で alacritty を動かすとマルチバイト文字の右半分が欠けてしまった。
これについては Cica というフォントに切り替えることで解消した。
ちなみに High Sierra ではこの問題には遭遇しなかった。

locale を自動判定してもらえない

シェルの起動時に locale が自動判定されず Powerline の設定を読み込むタイミングで Python がエラーを吐いてしまった。
これはうまく設定する方法がなさそうだったので、ひとまず rc ファイルに以下の1行を加えて事なきを得た。

export LANG="ja_JP.UTF-8"

ちなみにこの問題は日本語の表示とは逆に High Sierra では起きたが El Capitan では起きなかった(ただしこれについてはそれぞれの環境での設定の違いが原因であって OS のバージョンの問題ではなさそうな気がしている)。