rexecute: ファイルの更新を検知して指定したコマンドを自動実行するCLIツールつくった

そんなことより卒論書きなよって話ですが、texファイルの更新を検知して自動でビルドする仕組みを整備しました。

2年前に論文を書いていたときは、RubyのGuardを使っていたのですが久しぶりに試すと動かなくて、それを直すのも面倒だったので、少し汎用的に使えるツールをGolangでつくりました。

github.com

使い方

使い方はシンプルで、lsやfindでファイルの一覧をとってきて、rexecuteコマンドにパイプで渡すだけです。

$ find . -name '*.tex' | rexecute make build

デモの様子

みんなのGo言語で気になったところを読んでいたのですが、CLIツールの作り方の章や、golintやgo vetなどのツールの話がとても参考になりました。 このコマンドもUNIXの哲学にあるような、組み合わせて使える小さなコマンドになっているかなと思っています。

その他の使い方

汎用的なツールなのでわりと何にでも使えます。 例えばSphinxsphinx-autobuildとか使わなくても次のように使えます。

$ find . -name '*.rst' | rexecute make html

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

Released Kobin v0.1.0: Web Framework for Python3.

少し開発が停滞気味だったのですが、最近多くのアップデートを加えたので、v0.1.0をリリースしました。それに伴い、WSGIミドルウェアやWSGICLIの開発、ドキュメントの整備を行ったので紹介。

github.com

Kobin

Kobinの説明や使い方は、ドキュメンテーションを書いたのでここでは省略します。

また実際に自分でKobinとSQLAlchemy、Angular2などを使って、サンプルのアプリケーションを書いているので、とりあえず雰囲気を知りたい方はそちらをご覧ください。

Kobin Example Demo

WSGICLI

このツールはKobinに限らず、BottleやFlaskといった他のフレームワークでも利用出来ます。 Kobinはまだまだ開発途中な点もありますが、WSGICLIはもう十分に便利なツールかと思っているので、ぜひ使ってみてください。

簡単な使い方の例をいくつか紹介します。

ISUCONでPython実装をプロファイリング

このツールはLine Profiler連携とLive Reload機能のおかげで、ISUCONの問題を解くときにかなり便利なツールになったかなと個人的に思っています。

$ wsgicli run app.py app -h 0.0.0.0 -p 9000 --reload --lineprof

これを起動しておくと、手元のマシンでコードを変更・git pushして、git pullするだけで反映されます。 今はlineprofilerのみサポートしていますが、vmprofも追加予定です。

wsgicli profiling and live reloading

run コマンドには他にも、静的ファイルの配信機能や、WSGIの仕様(PEP3333)に準拠しているかチェックするミドルウェアフレームワークの開発に便利な機能があります。

wsgicli shellコマンド

django-extensionsのshell_plusをSQLAlchemyやpeeweeでも使用出来るようにしたような機能です。 Pythonの対話シェルを起動して、peeweeやSQLAlchemyのModelクラスをインポートしてゴニョゴニョすることがありますが、wsgicliのshellコマンドを使用すると起動時に自動でモデル定義を探索してimportしてくれます。

$ wsgicli shell app.py -i ipython

wsgicli shell

サポートしているPythonインタプリタは次のものです。

  • Python(Plain)
  • iPython
  • bpython
  • ptpython
  • ptipython

その他

その他にもlinebotのサンプルやWSGIミドルウェアを作っているので、ぜひご覧ください。

kobinpy · GitHub

kobin-linebot

WebフレームワークといくつかのWSGIミドルウェアwsgicli、サンプルアプリ、日英ドキュメントを全て1人で用意するのは思っていたよりも体力と時間が必要みたいです。 tomcriestieさんとか見てるとすごい勢いで開発していて焦りますね。 時間は思っていたよりも少ないみたいなので、2017年はもっとスピードを上げて沢山のコード書いていきたい。

実践 Python 3

実践 Python 3

Webフロント周りのパフォーマンスを計測・チューニングする

Github Pagesで公開しているポートフォリオサイトがそんなに色んな情報載せてる訳でもないのですが、遅くてあまり気持ちのいいものではないので、最適化していきます。

結論から書くと、2.87sぐらいかかっていた読み込みが1.57sぐらいになりました。 まだまだ細かいチューニングの余地はありますが、コストのわりに効果の大きそうなところを探って対処してみました。

  1. Chrome Developer Tools, Page Speed Insightsとかで原因を探る
  2. JavaScriptのminify
  3. 大きい画像はプログレッシブ形式のJPEGに変換
  4. ImageOptim
  5. CloudFrontでCache, 配信, HTTP/2対応

タイトルにはチューニングと書きましたが、基本的な最適化をちゃんとすればちゃんと表示速度が改善された感じです。

計測

まずは現状を確認

f:id:nwpct1:20161125170524g:plain

大きなヘッダ画像があるのでそこの読み込みが気になりますね。

Chrome Dev Tools

f:id:nwpct1:20161125170852p:plain

読み込み完了まで、2.87s。 グラフを見ると、bundle.js(このポートフォリオでは、Angular2 + TypeScriptを使ってます)とヘッダ画像が大きく特に読み込みに時間がかかっていることがわかります。

Page Speed Insights

Web Site: https://developers.google.com/speed/pagespeed/insights/?hl=ja

  • Mobile: Speed 56/100
  • Mobile: User Experience 97/100
  • PC: Speed 76/100

バイルの表示が特に遅いですね。 Google先生からのアドバイスは、

Web Pagetest

Web Site: https://www.webpagetest.org/

海外とかいろんな環境でのサイトのパフォーマンスをチェックできるらしい。 このページからのアドバイスは、

  • CDNを使う
  • 画像を圧縮する
  • 静的コンテンツをキャッシュする

最適化

JSのminify

まずは手軽で効果のありそうなところから。 webpackのhelpを見たら --optimize-minimize というオプションがあったので有効に。

webpack --optimize-minimize ./src/ts/index.js --output-filename ./public/js/bundle.js

f:id:nwpct1:20161125174452p:plain

  • bundle.jsのファイルサイズ: 592kB > 277kB
  • bundlejsの読み込み時間: 1.31s > 753ms
  • Page Speed Insights Mobile Score: 56点 > 59点
  • Page Speed Insights PC Score: 76点 > 87点

580msぐらい速くなりましたね。

ヘッダ画像の改善

プログレッシブ形式のJPEGに変換

905KBもあるのでこれも改善できそうですね。 JPEGには、左上から画像をパラっと読み込んでくれるベースライン形式と最初はモザイクが出るプログレッシブ形式があるみたいです。プログレッシブ形式のほうがユーザ体験は良いと言われているそうです。

最初のGIF画像を見てもらうと分かるのですが明らかにベースライン形式の挙動を示していますね。 rdjpgcomというツールで確認、imagemagickで変換出来るみたいです。

$ rdjpgcom -verbose img/eyecatches/autumn_leaves.jpg
JPEG image is 1500w * 1000h, 3 color components, 8 bits per sample
JPEG process: Baseline
$ convert img/eyecatches/autumn_leaves.jpg -interlace JPEG progressive.jpg
$ rdjpgcom -verbose progressive.jpg
JPEG image is 1500w * 1000h, 3 color components, 8 bits per sample

f:id:nwpct1:20161125180721g:plain

うーん、確かにモザイクが出るプログレッシブ形式ですね。ただユーザ体験がいいかというとなんとも言えない感じです。 よくなったのかイマイチ実感できないので、画像サイズを落としてみましょう。 画像サイズが小さくなって読み込みが早くなれば、わかりやすく快適になってくれそうです。

Optimで画像サイズを小さくする

Web Site: ImageOptim — better Save for Web

JPEG Miniは高いので、Optimを使って画像サイズを減らしてみます。 メタ情報やカラープロファイルを削除するらしいです。

  • 画像サイズ: 905KB > 817KB

まだ結構でかいですね。 この画像、1500x1000だったのですが、横幅1280pxぐらいが多いみたいなので思い切って減らしてみます。

  • 画像の読み込み時間: 1.47s > 988 ms
  • 画像のサイズ: 905KB > 626 KB
  • Page Speed Insights Mobile Score: 59点 > 63 点
  • Page Speed Insights PC Score: 変化なし

まだ少し重い気もしますが、横幅いっぱいに広げる画像なのである程度は仕方がないかもしれません。 別のところに手を付けます。

CloudFrontでCache, HTTP/2対応

Web Pagetestの結果では、海外からアクセスした際にレイテンシが大きいのか、CDNを使えとのメッセージがありました。 HTTP2のストリーム多重化で速くなることも期待して、AWS CloudFrontをかませてみます。 (余談: HTTP/2を使うかHTTP/1.1を使うか、どうやって判断するのか調べてみたんですが、TLSネゴシエーションの際にHTTP/2が使えるか確認してくれるみたいですね)

今回は検証目的なので、 http://c-bata.link は一旦そのままでこのURLをoriginにしてCloudFrontをかませます。 Webフォントをhttpで読み込んでいる部分があるのでそこを修正してCloudFrontのCacheをInvalidate後、何度かリロードする(Cacheさせる)と全体の読み込み時間: 1.57sまで上がりました。

f:id:nwpct1:20161126165720p:plain

グラフを見る限り、HTTP2のストリーム多重化がかなり効いているような気がしますね。

おわりに

最終的な表示はこのようになりました。 CloudFront対応はドメインと証明書の問題で、まだ http://c-bata.link のほうには反映していませんが、CloudFront経由後は読み込み速度が約半分の1.5s程度になり、GIFアニメーションの通り体感的なスピードも改善されたようです。

f:id:nwpct1:20161126170433g:plain

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

WEB+DB PRESS Vol.95

WEB+DB PRESS Vol.95