Memoエモさ駆動開発2019-11-23チーム異動後のターミナル周り半年前にチームの移動をした。プロダクトは同じだが、サーバからWebフロントへポジションチェンジした。以前からvimを使っていたが、Go言語はlspへの過渡期があったためIntelliJのvimバインドを使用するなどCLI離れをしていた。チームの異動後はTypeScriptを書くことが多く、vimをメインに使用するようになったため、CLI周りの見直しをよく行う様になった。dotfilesdotbotというdotfilesを管理するOSSを入れた。デフォルトでは、dotfilesへのシンボリックリンクを作成してくれる機能ぐらいしかないが、gitのサブモジュールとしてdotbot-brewなどを追加することで、brewを使ったパッケージの自動インストールなどもできるようになる。macOSとWSLを触ることが多いため、brew、apt、yayの三つに対応し、普段の開発に必要なツールのインストールを行うようにした。今まではシェルスクリプトでこのあたりの処理を書いていたが、メンテナンスするのが面倒になってきていた。dotbotはyamlだけメンテナンスすれば良いので楽。vim設定ファイルをシンプルに今までは.vimrcファイルをかろうじてneovim以外でも動くよう、ifなどで分岐をしていたが、これを一切やめた。deinとautoloadを使って、プラグインが読み込まれた時に設定も読み込まれるようにした。設定ファイルも自然と分割する様になるため、かなり見た目もスッキリした。副作用として、vimscriptちょっとかけるようになってきた。操作できるように正直今までのvimの使い方はvimmerとして酷いものだった。十字キー万歳、テキストオブジェクトをほぼ知らない、プラグインのキーバインドはデフォルト。これをかなり意識して直すようになった。実践vimを読み進めながら矯正中。yabaiターミナルからは少し離れるが、yabaiというOSSを使っている。タイル型ウィンドウマネージャなのだが、割とマウス操作もサポートしているのが特徴。今で、Macのタイル型ウィンドウマネージャAmethstなどを使用していたが、バグが多く挙動が不安定なため、使用を諦めていた。yabaiはその点、割と安定して動作している。(もちろんバグもあるが、設定でカバーできる)動画をPiPっぽく表示したり、Fn+マウスでリサイズ、移動、入れ替えなど様々な挙動ができる。skhdホットキー管理のOSSであるskhdは上記yabaiとセットで使うと便利で、yabaiのウィンドウレイアウトの変更やPiPの切り替え、ターミナルの起動など、様々な連携をホットキーにより設定できる様になる。Ctrl+Shift+Enterでターミナルが立ち上がり、ウィンドウの配置も自動で行ってくれるため、すぐにコマンドを打ち始めることができる。動画などはAlt+PでPiP表示にしたり、Alt+Eで分割の方向を変更したり、ウィンドウを半透明にしたりできる。yabaiとskhdの組み合わせを使い始めたことは今年一番実りのある行為だったかもしれない。ターミナルエミュレータ最近はkittyやhyper、alacrittyなど、クロスプラットフォームでGPUレンダリング可能なターミナルをいくつか試していた。どれも顕著なバグがあり(kittyはコピペ周りでバグるし、日本語ダメ。hyperは描画が崩れる&コピペバグる)またiTerm2に戻ってきてしまった。WSLで使えないため、まだまだ彷徨う必要がありそう。(goroutine割り込み)前回mjhd.hatenablog.com最近、面白いツイートを見つけた。inliningの複合技により引き起こされていると言う。今回は、ゴルーチンの内部動作から、なぜこのバグが引き起こされたかをまとめたいと思う。そもそもゴルーチンってどうやって動いてるんだっけ?GolangではOSの管理するスレッドとは別に、論理プロセッサと独自のスケジューラを持ち、ランタイムが管理をしている。各コンポーネントは以下のように説明される。論理プロセッサよく見かけるGOMAXPROCS変数はこのうちPに該当し、論理プロセッサの数を表す。golangのスケジューリングは二つの階層に分けて説明でき、一つ目は、M(スレッド)とP(論理プロセッサ)の割り当てと、もう一つがP(論理プロセッサ)とG(ゴルーチン)の割り当てである。work-stealingグローバルとして、キューを持ちPに割り当てされていないゴルーチンを保持する。各P(論理プロセッサ)もそれぞれキューを持ち、割り当てられたゴルーチンを保持している。各Pはもし自分のキューにゴルーチンが存在しなければ、他のPからゴルーチンを奪い、実行する。stealingという。奪えるゴルーチンが存在しなければ、グローバルなキューからゴルーチンを割り当て、実行する。ゴルーチンの実行が終わると、Pは別のゴルーチンへコンテキストスイッチをし、実行を続ける。これを繰り返しゴルーチンは処理されている。現在の定義だと、Pがゴルーチンが終わるまで次のゴルーチンへコンテキストスイッチできないのである。ここで必要になる機能が、ゴルーチンの割り込みである。ゴルーチンの割り込みとは、ゴルーチンの実行中でも他のゴルーチンに処理を譲る(または奪う)ことで、平等に平行に処理をするための機能のことである。preemption)」という方式が実装されている。これは、コンパイル時に任意の箇所に割り込みコード(他のゴルーチンに処理を譲る処理)を埋め込むことにより、ゴルーチンが他のゴルーチンに処理を譲りながら実行できるようにしたものである。基本的に、この割り込みコードはインライン化されていない関数呼び出しなど周りにコンパイル時に挿入される。関数呼び出しが合図になる。して掲げられている機能なのだが、上記の協調割り込みには強めのループなどのようにエッジケースが存在するため、非協調割り込みという、強制的にゴルーチンの処理を奪う方式を採用しようという動きがある。インライン化対応が行われた。Unlockなどがインライン化されてしまい、割り込みチェックが入らなくなってしまった。よって、無限にブロックし続けるプログラムが誕生した。LSPRubyの静的型チェッカー、「Sorbet」がオープンソース化された。LSPも実装されており、これだけRubyもシェアがあるので、覇権を握れるのでは。手元にちょうど良いRailsプロジェクトが合ったため、導入してみた。Started通りに進めていく。initをするぐらいで一瞬で終わった。falseと書いてあるため、型チェックはされない。trueに変更してみると、例えばRailsのControllerなどでは大量にエラーが出るはず。これは、Railsが実行時にroutingなど動的に様々なシンボルを生成しているためで、このままだと使い物にならない...。Rails対応sorbet-railsというRails向けsorbetの型定義生成ツールがある。これを入れれば一通り開発ができるようになる。level(ファイルの先頭にあるtyped)を上げてくれる。trueとなり、型チェックが通るようになる。LSP導入せっかく静的型付けができるようになったので、LSPによる定義へジャンプや補完、型チェックを使いたい。LSP導入の方法は色々調べたがドキュメントが全くなく、自己流で導入した。(おそらく今後この辺のドキュメントも揃ってくると思う)まずは、公式レポジトリをクローンする。https://github.com/sorbet/sorbet次に、README通りにbazelや必要なライブラリのインストールを行う。macユーザで今までC++で開発をしたことがないユーザは、以下のコマンドも必要かもしれない。/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg準備ができたら、bazelでビルドを行う。この時、プロダクションビルドのオプションを指定する。いうバイナリができ上がる。このバイナリを以下のようなオプションをつけて、プロジェクトのルートで実行するとLSPとして待ち受けるようになる。.(--no-configを設定しているが、これは簡単のためであり、本来はプロジェクトごとの設定ファイル(sorbet/config)を読み込むべき)これをvimやVSCodeに設定すれば、補完や定義へジャンプが有効になり、快適なsorbetライフが送れるようになる。inliningとは、前回の記事でも紹介したインライン化をより積極的に行うようになる機能のことである。前回の記事からの引用だが、Goのコンパイラは、関数が以下の条件に当てはまるとき、関数を直接、呼び出し元に展開する最適化を行っている。(これも上のコマンドで解析結果を確認できる)コードが80ノード以下(Go1.4以前は40ノード)関数呼び出し、ループ、ラベル、クロージャ、panic、recover、select、switchなどの複雑な構文を含まない以上がインライン化の大まかな条件であった。ここには、関数の呼び出しという項目があり、今まで関数のインライン化は一番末端にある関数(木構造でいう葉っぱ)でしかインライン化を行なっていなかった。inliningは、これを改良し末端以外の関数でもインライン化を行うための最適化である。inliningの有効無効に関わらない話だが、インライン化により、スタックトレースを出力した際などに実際のソースコードとの差異が出てしまう。以下のような関数があったとする。b((nil)(*s))}このコードがもしインライン化されたとすれば、以下のようなコードになる。dereferenceが発生した場合、以下のようなスタックトレースが表示されてしまう。bの情報が消えており、デバッグが困難になってしまう。inliningでは、インライン化した関数のPCとソースコード上の位置を保持する木構造をテーブルとして表した構造体(InlTree)を生成し、シンボルテーブルに格納する。実行時は格納されたテーブルから実際のスタックトレースを生成し表示を行うことで、インライン化をしたとしても正しく出力が行えるようになる。制限として、以下のように引数は省略されてしまう。+0x2どのぐらい早くなるの?ベンチマークによると9%ほどパフォーマンスが改善するらしい。inliningの恩恵を受けることのできる部分があるため、以下のような改善を繰り返していくことでGo全体のパフォーマンスが向上するのではと思う。inlining編)Tweet広告を非表示にするコメントを書くもっと読む2019-04-23WSLのIO遅いよ問題WSLは理論的にはLinuxカーネルを起動するオーバーヘッドがなく軽量に動作するはずなのだが、実際に動かしてみると色々ともっさりしている。installなどが重たすぎて永遠に終わらなかったりエラーが出てしまったり。この辺のもっさりは、WSLのIOが重いことに起因する。www.phoronix.com↓のスレッドではWSLのIOはなぜ遅いのか問題が議論されている。github.comSvenGrootさんの説明1LinuxのIO操作とWindowsのIO操作の設計が根本的に違うことが原因。解決しようとしたら、Linuxの挙動を完璧に再現しなければならない。Defenderやサードパーティのウィルス対策ソフト)などの沢山の関係者がいて、複雑でとても進みの遅い作業になる。Updateではstatコールのパフォーマンスを向上させる新しいファイルシステムAPIを導入した。この変更を知らせ、使用してもらうために内外のベンダに働きかけている。ファイルシステムのパフォーマンス問題は難しい、けど改善を続けてくよ。苦しみはわかるけど問題を無視してるわけじゃないよ。ファイルのIOにサードパーティが独自の処理を挟めるもの。Defenderはこれを使ってファイル変更の監視をしているSvenGrootさんの説明2ここまでの問題は簡単に言えば、"NTFSは遅い"か"DrvFSは遅い"だと思う。IOサブシステムはWindowsとLinuxでかなり違う設計になっている。大きな違いは以下の3点。Linuxはトップ階層にキャッシュを持っていて、キャッシュに存在するエントリに関してはFS内部を探索しなくても返すことができる。Windowsにはこのようなキャッシュがなく、ファイルシステムに大きく頼っている。Win32の「C:\dir\file」のようなパスは「\??\C:\dir\file」というNTパスに変換され、「\??\C:」部分はObjectManagerが管理する\Device\HarddiskVolume4などへのデバイスオブジェクトへのシンボリックリンクを表している。一度このようなデバイスオブジェクトを発見すると、Windowsは残りのパスを単純にファイルシステムへ託す。ここがLinuxのVFSが行うような中央集権的なパス解析との違いである。WindowsのIOスタックは拡張性を重視しており、ファイルシステムへのIO操作要求を実行する前にフィルタドライバを設定することができるようになっている。これは、例えばウィルススキャン、圧縮、暗号化、OneDriveのような仮想的なファイル、アプリの起動高速化のためのpre-fetchingなどなど至る所で使われている。Windowsをクリーンインストールしたとしても、すでにWindowsはある程度の数のフィルターが特にシステムドライブ(C:)に関しては動いている。(なのでD:ドライブや他のパーティションが存在するマシンなら、よりフィルタが少ない傾向にあるシステムドライブ以外を使うことを推奨する)これらのフィルタは沢山のIO操作、特にファイルのオープンと作成に設定されている。NTのファイルシステムAPIはパスベースではなく、ハンドルベースで設計されている。ほとんどいかなる操作もはじめにファイルを開きハンドルを取得する必要があり、この操作はパフォーマンスに影響する。APIでファイル削除の1コール(DeleteFileなど)を実行したとしても、実際にはOpen/Close操作が走っている。前にリリースしたDrvFSの大きな改善は、ファイルの情報取得のためにファイルを開かなくても良い新しいAPIを用意することだった。基本的にファイル操作はLinuxよりもWindowsの方が重い。ファイルのメタ情報に触れる操作は。Manager*2、フィルタ、そしてNTFSに広がっている。単純に「NTFSが遅い」というだけならNTFSの最適化の修正を行えば良いが、問題は広大なコンポーネントに広がっており、銀の弾丸がない状況である。内製のフィルタだけならまだいいが、サードパーティのフィルタが内部で何を行なっているかは知るすべがないので、各ベンダと共にこれらの問題の改善を試している。ファイル情報を取得する新しいAPIを導入し、フィルタドライバもそのAPIをサポートした時、まだ新しいAPIに対応していないフィルタがインストールされていたとしても正常に動作することを保証しなければならなかった(基本的にはOpen/Query/Close処理へフォールバックする)。その他もこれをサポートしていることを確認し、最大のパフォーマンスの恩恵を受けられるようにするためには沢山の時間と労力がかかった。同じことが大文字小文字を区別するディレクトリなどにも言え、変更後の動作をフィルタのエコシステムが正常にハンドルできるのか確かめなければならない。...中略...また、単純に「Windowsが遅さの原因」と言うわけではなく、WSLの影響もある。WindowsとLinuxのパス解析の挙動の大きな違い(Linuxは中央集権、上でも述べた通りWindowsはファイルシステムに任せている)がある。LinuxアプリはLinuxの挙動を想定して作られている。我々も慎重にその挙動をエミュレートし、不幸なことにも沢山のIO操作をファイルシステムに送ることになってしまっている。statコールも、Linuxはキャッシュ*3にヒットさえすればLinuxカーネルが全体を応答するが、WSLではフィルタ全体を走査する複数のリクエストをファイルシステムに対して送らなければならない。我々はWSLで余計な処理が必要にならないよう沢山の作業を間も無くリリースされる1809で行なった。APIが違う以上、ここにはどうしても余計な処理が必要になってしまう。Partnersと共に取り組んでいかなければならない問題である。いって諦めるわけではないよ〜。外部入出力を管理するコンポーネント。02:40WSLのIO遅いよ問題Tweet広告を非表示にするコメントを書くもっと読む2019-03-092019年最高のWSL環境を求めて2016年、僕はWSLに出会い感動してからというもの、「最高のWSL環境を求めて」さまよい続けました。来る日も来る日も「Windowsは最高・・・Windowsはクソ・・・Windowsは最高・・・」と呟きながら花びらを散らし、バグのあるWindowsアップデートにも負けず、急に唸りだすRuntimeBrokerたちにも負けず、費やした時間は数知れず。時にはディストリビューション壊して再インストールして、時にはHyper-Vに浮気をしたり、時にはiMacを買ってそっちに逃げたりしながら・・・。今回は2019年、僕が「最高」だと思うWSL環境をまとめたいと思います。過去の記事mjhd.hatenablog.comXサーバLinuxのGUIアプリケーションを表示するために必要なXサーバ、以前はVcxsrvを使っていましたが、現在のおすすめはX410です。シェアウェアだけあってとても安定しています。入れとけば完璧に動く、という安心感は他にありません。今なら4700円割引(ほんとか)らしいです。tilixなどを使っていましたが、やはり機能面と安定感の両立がなかなかできませんでした。wslttyは機能面・デザイン面で劣るし、gnome-terminal、tilixなどをX11越しで使うのはIMEの設定が必要であったりクリップボードが安定しなかったり起動がもたついたり、なかなか満足いく体験には至りませんでした。現在はalacrittyを使っています。alacrittyはGPUを使用した高速なレンダリングが特徴の端末で、マルチプラットフォームなので機能面での不足はあまりありません。Rustさまさまです。描画がとにかく早いので、WSL上でzsh使ってももたつきがほとんどないです。Windowsの場合、初回起動時に「ホームディレクトリ\AppData\Roaming」以下に「alacritty/alacritty.yml」ファイルができるので、いい感じに設定してあげてください。theme」で検索すれば有名な色設定をコピペできます。ConPTYの設定項目をtrueにしておくと良いです。Microsoftも頑張っています。github.comあと、Terminus、FluentTerminalという端末もモダンでWindows10らしさがあって良いです。発展途上ということもあり、特にパフォーマンスの観点でオススメできません。今後を見守りたいです。technologies.今後の改善点やはりWSL最大の不満点は、Windows側からWSLのFSをいじれないことでしょう。ここもMicrosoftは頑張っていて、UNIXドメインソケットを実装したことによりWindowsとWSL間の高速で汎用的な通信が可能になり、これを通してファイルを共有するという機能が盛り込まれると発表しています。(このアップデートが入るまではsftpやftpで共有するぐらいしか手段がなかった。Dokan使ってマウントしたり)WindowsからWSL側のファイルシステムが気持ちよく触れるようになれば、例えばWindowsネイティブのIDEからWSL上のプロジェクトを開き、ビルドなどはWSL上で行う、といったシームレスな開発ができるようになる予感がしています。さまよい続ける必要がありそうです。Microsoft頑張って。11:512019年最高のWSL環境を求めてTweet広告を非表示にするコメントを書くもっと読む2019-01-14サウナー用語2019年5月更新この頃サウナにはまっており、話題のサービス「サウナイキタイ」のサウナー達によるレビューを読み漁ってたらなんとなくサウナー用語(サウナスラング)がわかってきたのでまとめる。人間の三大欲求の一つ。サウニングサウナに入ること。サウナ->水風呂->休憩のサイクルを繰り返すこと。ライドオンサウナ施設に突入すること。SEO耳栓SEOの辻さんが装着している耳栓。飯サウナ施設や近所で食べられるご飯のこと。サウナ後の空腹状態で食べる。広さや設備、温度が語られることが多い。アフターサウナサウニングが終わった後のこと。ととのうサウナによってある種のトランス状態に入ること。(こっちの方が本物な気がする)ととのいポイントサウナ外にあるデッキチェアなど、サウナ->水風呂の後に精神統一できるスペース。「上野サウナ&カプセルホテル北欧」のこと。「北欧に行く」と行ったら旅行に出かけるわけではなく、「上野サウナ&カプセルホテル北欧」で外気浴を満喫することを指す。静岡にある「サウナしきじ」のこと。全国からサとりを開くためにサウナーたちが集まる聖地。水風呂に浸かると「宇宙が降りてくる」らしい。緑のラッコ草加健康センター。チンピリと広いサウナ。草加健康センターへ行くこと。温度設定の強めなサウナ、水風呂のこと。ごろも水風呂に浸かってしばらくすると皮膚の周りに出来上がるぬるい水の膜。水流が当たるとはごろもが取れるため、冷たく感じる。グルシン水風呂の水温が一桁台(シングル)であること。バイブラ浴槽内に設置される泡を放出する機械。水風呂内に設置された場合、体感温度が下がる効果がある。水風呂において、循環した水を冷やすための機械。これが効いてないと人が入るたびにぬるくなっていく。<p>引用をストックできませんでした。<p>限定公開記事のため引用できません。