kmuto’s blog

はてな社でMackerel CREをやっています。料理と旅行といろんなIT技術

『詳解 システム・パフォーマンス第2版』制作の思い出

オライリー・ジャパンさんの『詳解 システム・パフォーマンス 第2版』が無事刊行されたようでめでたい。

前職で制作のお手伝いをしていたものの、完成一歩手前である再校まで作成した(電子PDFとEPUBの準備もしておいた)ところで退職となったので、行方を気にし続けていた。

本書は、コンピューティングパフォーマンス分析の第一人者と言える、Brendan Greggの著作。最近だとeBPFの分野で有名か。著者紹介にはNetflixと書いてあるけど、昨年5月にIntelに転職したらしい。

旧版(邦訳版は2017年)はLinuxSolarisだったが、今回はほぼLinuxに絞っての解説となっている。

その解説は生半可なものではなく、CPU、メモリ、ディスク、ネットワークインターフェイスはもとより、あらゆる面にわたってのパフォーマンス分析が、場面に応じた多数のツール群を活用して実行される。Greggの脳内が紙面にダンプされているような感覚だ。

仕事的には4章の可観測性ツールや11章のクラウドコンピューティングあたりは関係深めかもだけど、関心的には6章のCPU〜10章のネットワークといった裏側にある泥臭い世界が大好き。

とんでもない物量に圧倒されるが、これを読んでいけば、パフォーマンス問題にアタリをつけたり、適切なツールで調べたりすることがずっと容易になるだろう。

940ページの鈍器の本書、Linuxほかシステムのパフォーマンス分析に関わっている方々にはぜひ手にしていただきたいと思う。

以下はおまけ。

紙面DTPについては、分量が多くてRe:VIEWファイルの加工調整と、見た目・ページ繰りの調整は確かに時間はある程度かかったが、想定の範囲内ではあった。

本書で最も恐しいのは60ページにもわたる索引で、これは原書に従っている。原書での専門のindexer、はりきりすぎでは…?という気がするが、「邦書でもこれと同等にやりたいのですがなんとかなりませんか…」とオライリー・ジャパンさんからの依頼があり、こちらで作成している。

悲しいことに翻訳の時点で原書データの索引はすべて喪失していたので、以下の手順をたどって索引付けを行った。

  1. 原書のDTPデータ(InDesign)から索引をテキスト化し、「索引項目 <タブ> ページ番号 <タブ> 索引項目」の形にする。「102-103」などの範囲になっているものは索引項目にBEGIN、ENDのマークを付けておく(例:life cycle◆BEGIN◆ 102)。親・子・孫の索引については、索引項目の箇所を「親<<>>子<<>>孫」のようにする。see also形式のものはページ番号の代わりにそれを入れておく。
  2. 上記をスプレッドシートにインポートする。
  3. 1列目の索引項目の単語に、訳文を見ながら訳語を当てていく(3列目は原書と照合するために英語ママにしておく)。できるだけ一括置換で多いものから進める。1回しか登場しないものをがんばっても意味がないので。
  4. 2列目のページ番号で原書を見て、和書PDFと原稿Re:VIEWファイルと照合し、@<hidx>で1列目の索引項目を入れる。索引の訳が完成していなければ判断して訳す。
  5. 全部入ったらsee also部を最初のRe:VIEWファイルの末尾にでも@<hidx>で入れておく。
  6. BEGIN/END関係ができていないものを雑に書いたツールでチェックする。
  7. MeCabソート有効でRe:VIEW PDFのビルドを実行して __REVIEW_BOOK__.idx (および.indファイル)ファイルを作成する。
  8. 内部索引ツールでidxからソートし直しおよびBEGIN/END処理、seealso処理を行い、indをテキスト化したのに近いtxtファイルに変換する。
  9. おかしなもの(読みミス、BEGIN/END非対応、語句がページにまったくヒットしないなど)がないことを確認したら、編集者にtxtを引き渡す。
  10. 以降はページが大幅に変わらない限りは、編集者作業用のtxtファイルからindファイルに変換する。

3.と4.の作業についてはパラレルでできるので、社内で分担して処理したが、当初はなかなか進まずに苦戦。だんだん自分も同僚もペースが上がってきて、予定時間どおりで終わったのは自分の見積りが素晴しかったのか……? 今回の場合は和訳において独自の節項組み換えなどは行われていないため、範囲の追従についてあまり悩まずに済んだのが幸いだったと言えよう。

テレワーク用にアーム付きモニタ台を構築した(ハンズは神。そして椅子はどうしたものか…)

はてなに入ってから毎日のかなりの時間が、アクティブ・パッシブ含めたビデオミーティングに費されている(前職では週1かつパッシブなミーティングだったのとは雲泥の差である)。めげそうになりながらもミーティング自体はなんとか慣れてはきたのだが、ホームテレワークの問題として挙げられる「家人とのミーティング競合」がいよいよ顕在化してきた。

同じくミーティングの多い相方とは朝食時に当日の時間帯のすり合わせはするものの、どうしても互いにアクティブミーティング時間で競合するもの、あるいは突発的に競合するものが発生する。

OpenCommのほうだとマイク指向性が合っていて相方の声は入りにくいものの、耳が開いているので会話相手の声より相方の声が入る。ではノイキャン付きのH700のほうはというと、相方の声は聞こえにくくなるものの、マイクが集音しすぎてむしろ相方の声のほうを拾ってしまう……。

この状況は、生半可なパーティション程度では防音も無理なので、物理的に距離を離すしかないね、ということで、ミーティング競合の際は後手がダイニングテーブルを使う、という方向を検討した。

当初はラップトップを移動して使ってみてはいたものの、2人ともミーティングでは大きな画面でないと不便すぎる。かといってダイニングテーブルにモニタを設置するのは危ないし、落ちつかない。 いろいろ検討した末に、移動ラック棚を作り、そこにアームを付けるという考えに至った。かつ、ダイニングで使わないときには邪魔なので、作業場のキャビネットを覆うように置けるようにしたい。

Illustratorでさくっと図面を引く。

設計図

棚は信頼のエレクターシェルフ。キャビネットとダイニングテーブルとの兼ね合いで、ポストが定型の600mmでは短すぎるし、650mmでは長すぎる。オーダーになるがさほど高額にならずに630mmにできるようなので、それを前提にすることにした。ポストは2本組売りなので、この場合、800mm 1本、630mm 1本が無駄にはなる。

下部はキャビネットが入るよう3方クロスバー、天板はワイヤーシェルフ。1本だけポールを長めにし、そこにアームのポールを被せるイメージとなる(ネット情報で実践されている方を確認)。

キャスターについては、ナイロンだとフローリングがやられてしまうし、ウレタンは剥がれて結局フローリングのワックスがけが面倒になるので、一番高いけどエラストマーキャスターを想定(パーツで一番高い……)。ちょっと困ったこととして、キャスターの高さの説明がわかりづらく、最大6mmだろうか?とというあやふやな状態となった。ダイニングテーブルとの隙間がシビア(設計時点では12mm)なので、ここが予想より大きいと不安がある。

ネットでも発注はできるが、キャスターの高さが心配だったので、エレクターシェルフのオーダーを扱っている新宿ハンズへ。ここからが「ハンズは神!」と思わせる素晴しいカスタマーサクセス対応のターンだった。

  • まず、高さは問題ないとわかった。むしろこの6mmは発生しない。
  • で、ポストのオーダーをしようとしたのだけど、そのやり方だと2本が無駄になるし、オーダーは時間が1ヶ月くらいかかる(かつちょうどモデルチェンジ&値上げが始まりそうなタイミング)、
  • …ので、むしろ650mm 2本と800mm 2本にして、800mmの1本以外はハンズ側でカットして630mmにするのはどうでしょう?という提案を受ける。エレクターシェルフのポールも切れるの!?
  • それ最高じゃないですか、ということで発注。モデルチェンジ前の品の在庫確認を手際よくしていただく。
  • カットについては別フロアなのだけど、対応のスタッフさんがそのまま付いてくれて、必要事項の記入の支援と、カットスタッフへの事項連絡を進めてくださった(まだモノがないので説明図のみでの指示)。
  • 後日、品物が入荷したという電話連絡をいただく。カットした旨と最終寸法の連絡、到着日折衝と流れるように進んだ。

ハンズには工作まわりでお世話になることはたまにあったけど、今回はこちらの考えに対してベストなソリューションを出してくれたので本当に良かった。

ということで、日曜日にハンズからの品が到着したので、組み立てる。アームとモニタは事前に購入済み。

正面

背面

ででーん。

アームは信頼のエルゴトロンLX。ほぼぴったりの高さで被さり、蓋もできる。シェルフのテーパーが1つ必要なのだけど、今回のセットの予備でちょうど1つ余るので、それを使うだけ。

モニタはDELLの27インチ4K S2722QCにした。モニタについては、フルHDでは表示したい情報に対して足りない、USB-Cのモニタ出力&給電に慣れるとUSB-C以外ない…ということで選んだが、想定利用頻度に対して少々オーバースペック感はある。相方が輝度や反射に弱いので、フィルムも貼り付けた。

さて、肝心の使い勝手だが、棚、キャスター、アーム、モニタ、いずれもとても良い。完璧?

モニタが重いため、重心バランス的にアームを伸ばす方向には一定の制約がある(無茶な方向にすると棚ごと倒れる)が、予定していた伸ばし方の範囲では何も問題なく、安定している。

キャスターも軽く静かでするする動く。ロックもかけられるので安心。

残る課題は椅子。

食卓椅子で2時間ミーティングは辛いし、アームレストもない。ダイニングに置いても違和感がなく、2人のどちらも座れるアームレスト付きオフィスチェア、かつ相方の条件としてアームレストは90度までの回転が必要(普通のオフィスチェアのアームレストだと肘が落ちる模様。35度でもダメだった)というのがあって、調べているけど決め手がなくムームーしているところ。

そもそもアームレストを90度回転できるもの自体が少ないのだった。

  • イトーキ カシコチェア: 相方が使ってるけど自分にはまったく合わなかった。腰が気持ち悪い
  • イトーキ fチェア: 座ってみたところでは相方はOK、自分にはリクライニング抵抗力がなさすぎて固定にしないと無理め
  • イトーキ Prao: 20年前の商品で、形があまりにももっさり…
  • エルゴヒューマン: ジェネリックアーロン。これをダイニングに置くのはどうなの

うーん……。

『Software Design』2023年2月号を読んだ

gihyo.jp

今回もメモで。「AWS活用ジャーニー」が、今勉強しているところと重なって特によかった。

  • 結城浩の再発見の発想法」
    • フィルタのお話。すべてそろってから処理をするのではなく、ストリームのような流れとして考える、なるほど。そういえば、いつのまにか tail -f /var/log/syslog | grep hoge みたいなのでgrep--line-buffered を付けなくてもよくなったのかな。データにもよるか。
  • ドメイン駆動設計入門」
    • 特集1記事。いわゆるDDDの話。ドメインは、ソフトウェアが対象とする領域のこと。ドメイン駆動設計では、事業活動とソフトウェア設計を直接強く関連付けることを目標とする。事業活動は複雑な業務ルールからなり、ドメインの複雑さがソフトウェアの複雑となる原因。
    • ドメインモデル。複雑な業務ルールを動くソフトウェアとして実現して変更を楽で安全なものにする手法のためのモデル。ドメインの事業活動の複雑さの要点を整理・簡略化したもの。「カジュアルな会話」「ラフスケッチ」を重視。ソースコードで表現。3つの目的「設計の基本構造」「抽出した業務知識」「意図伝達の中心となる言葉」。
    • 知識をかみ砕く。業務のやり方や決め事を理解し、重要な点を見い出し、コード化する。
    • 業務を書く理解していくことで、重要な経営課題を捉え、設計に反映する。
    • 用語の部門や人による違いを、一貫した同じ言葉であるユビキタス言語にして解決する。当面の課題にとって重要な言葉から選び、意識して使う(全員の会話、クラス名やメソッド名、コミットログなど)。選び抜かれた軸となる言葉の集まりがドメインモデルとなる。
    • 当面の課題に必要・重要な情報だけを抜き出す=モデルを作り出す。
    • モデルと実装を一体化、バインドする。「設計にそのまま使えるモデルを使って知識の整理や意図の伝達も」「設計、知識の整理、意図の伝達の3つの用途に役立つ1つのモデルを見つけ、成長させていく」。バインドのパターンとして値オブジェクトや集約。
    • アプリケーション開発での適用。複雑な業務ロジックに関心を当てる。複雑な業務ロジックを独立した構成要素として分離。アプリケーションのほかの構成要素を業務ロジックを表現した構成要素に依存させる。複雑な業務ロジックに直接関係する部分に焦点し、そうでない部分は周辺的な関心事として分ける。
      • ドメインモデルで業務ロジックを独立させる。
      • ドメインモデルを中核に、周辺要素(画面、データベース、通信など)がある。つなげ方には、ドメインモデル+3層構造、ドメインモデル+ポート&アダプター、クリーンアーキテクチャといった考え方がある。
    • 複雑な業務ロジックとそうでない要素の混在を分離する。表現クラスを厳密に分離、複雑な業務ロジックを表現するクラスだけをドメインモデルに置く、両方のクラスを合成するクラスを作成する、合成用クラスのオブジェクト組み立てや業務ロジッククラスオブジェクト抽出を処理するクラスをドメインモデルの外に置く。混在はよく起こるので、こまめにリファクタリングする。積み重ねることで、業務知識の深い理解となり、隠された概念を明示的にする方法を発見できる。
    • ドメイン駆動設計とXP(特にリファクタリング、顧客との頻繁な対話)とは相性が良い。アジャイルウォーターフォールでもある程度は取り入れられるが、効果や速度などに差が出るだろう。
    • 2章以降はかなりガッツリDDD実践。ちょっと腰据えて読まないと理解できなさそうなので、後回しで。
  • 「今さら聞けないログの基本」
    • 特集2記事。syslog、journald、Apache/nginxのアクセスログの見方と、自作のアプリケーションからログを書き出すときのメッセージプラクティス。ログフォーマットはぜひ機械処理しやすいものでお願いしていきたい。
  • 「画像生成AIのしくみ」
    • DALL-E2やStable Diffusionなどのテキストからの画像生成(text-to-image)AIの仕組みの話。テキストエンコーダと画像生成器からなる。エンコードされたテキストは低次元(数百次元程度)ベクトル化される。意味的に近いベクトル同士は空間的にも近く、単語に対応するベクトルと、その単語の画像に対するベクトルは近いと期待される。類似品も近くなるし、かけ離れたものだと遠い。
    • DALL-EはテキストエンコーダにTransformer、画像生成にVQ-VAE。モデルパラメータは120億(従来は数千〜数億程度で圧倒的)。画像とALTテキストのクロールで2.5億の画像・キャプションペアを収集。質を量で圧倒。
    • DALL-E2・Stable Diffusionでは大規模text-to-imageに適したアーキテクチャを追求し、テキストエンコーダに事前学習済みTransformer、画像生成に拡散モデル。
    • 自然言語の理解、テキストの適切なベクトル化。言語モデリングによる事前学習。トークンに分割して確率分布をモデリングする。CLIPテキストエンコーダは画像との対照学習で訓練されている。
    • 訓練データを増やすほどモデルの精度が高くなる。スケーリング則。大規模言語モデルの例がBERT、T5、GPT-3。
    • わかりやすい指示により回答の精度を上げる。プロンプトエンジニアリング。
  • 「『らしさ』の本質に迫るGo言語」
    • H.Sakiさんの新連載。Goが守りたいシンプルさは「明確で過不足がないこと」。書き手の意図が明確であること、コードがどのように動作するか明確であること。
    • Goはコンパイル前のコード段階だけでなく、コンパイル後の段階まで含めてのシンプルさ・明確さを要求。
    • 過不足がない。1つだけあるベターな書き方を提供する。スケーラビリティを確保した、優れたプログラムを書くために必要、という軸。長期的に見てメリットがあるよう設計された取捨選択。
    • コードに信頼性、開発に生産性をもたらす。
  • 「最強の開発環境探求の道」
    • fzfの使用方法。使ってなかったけど、便利なのかなこれ。「| fzf」を付けたり、xargsを書いている間に試行のほうが早いこともありそうなので、使い勝手が難しめか。historyと組み合わせるのは確かにありかも。
  • 「リソースから考えるBCPの手引き」
    • 組織的リソース=人・組織・建物・金。脅威に対して事前に準備・対策を考えられる。脅威により対応の時間的余裕が異なる。事前予測できる脅威に対して備え、事業への影響を最小限にする。
    • 組織的リソースそれぞれの観点での、被害を極小化するための事前対応、被害拡大を防ぐための初動対応、事業復旧のための復旧対応。
    • リソースの「代替」がBCPでは大事。「〜がないからできない」では継続できない。
    • 地震の場合は1〜3日を災害対応、4日以降から事業継続へシフトしていく。
  • AWS活用ジャーニー」
    • 今回はDynamoDB。フルマネージドなキーバリュー型NoSQL DB。NoSQLなので、少ないテーブルに収納することがベストプラクティス。1アプリケーション1テーブルくらいを目指したい。CRUDに相当するAPIがあるが、Scanはフルテーブルスキャン相当で効率が非常に悪く、できるだけ使わない。PutItem、GetItem、UpdateItem、DeleteItem、BatchGetItem(最大100個)、BatchWriteItem(最大25個)、Query、Scan。
    • テーブルはスキーマレス。プライマリキーはある。パーティションキーのみのシンプルプライマリキー、パーティションキーとソートキーの組み合わせの複合プライマリキーの2種類をサポート。
    • キーに紐付けて項目を保存する場所がパーティション。カーディナリティが低い(データの種類が少ない)属性をパーティションキーに選ぶと特定パーティションにアクセスが集中するホットパーティション問題が発生する。
    • 読み取りAPIが限定的なので、LSI(ローカルセカンダリインデックス)を使う。テーブル属性→インデックスコピーを射影という。属性が不足すると追加データ取得が必要、不要な属性が多いとストレージ消費。同じパーティションキーを持つ項目の合計サイズは10GB。LSIを作成できるのはテーブル作成時のみで、5個まで。
    • GSI(グローバルセカンダリインデックス)。非キー属性に対するクエリに強い。常にQueryかScanを使用。GSIは20個まで、テーブル作成後でも作成できる。
    • 読み書きに応じてのキャパシティユニット消費(RCU/WCU)。料金モデルを決定するのがキャパシティモードで、プロビジョンド(秒あたりのRCU/WCUを指定し確保。リザーブドもあり)とオンデマンド(実際の消費ぶん)がある。プロビジョンドで足りないとスロットリングする可能性。
    • テーブルクラス。標準、標準-IA(アクセス低頻度用。保存料金安・RCU/WCU高)。
    • 標準バックアップ。PITR(ポイントインタイムリカバリ)は過去35日の任意の時点に復元可。オンデマンドバックアップは35日以上の長期保存向き。実際には巻き戻しではなく新しいテーブルが作成される。復元後、手動設定をする必要あり(Auto Scaling、PITR設定など)。
    • AWS BackupはDynamoDBとも統合。
    • 項目のイベントに対してストリーミング。DynamoDB StreamsはLambdaとDynamoDB Streams Kinesis Adapterに対応。Amazon Kinesis Data Streams for DynamoDBはLambda・Kinesis Data Analytics・Kinesis Data Firehose・Glue Streaming ETLなどに対応。全文検索をOpen Search Serviceに投入するなど。
    • DynamoDB Acceralator、インメモリキャッシュサービス。マイクロ秒単位の応答対応。API互換なので透過的、アプリケーションはエンドポイントを切り替えるだけ。
    • DynamoDBグローバルテーブル、マルチリージョン化。自動でレプリケーションされる。
  • 「魅惑の自作シェルの世界」
    • 終了ステータスとシグナルの実装。execでEACCESとENOENT以外のケース、どういうものがあったっけかな。
  • 「現場を支えるPlaybook」
    • Ansibleで個々のタスクに分かれがち・作りっぱなしだったのを、Roleで再利用しやすい単位に再構築してみた話。Terraformあたりでも類似のケースありそう。
  • Kubernetesネットワークのしくみ」
    • 最終回だった。minukubeでローカルKubernetesクラスタを作り、サービスメッシュのIstioを実行する。外部からのアクセスはminikube tunnelを通してIstio Ingress GatewayGateway→VirtualService→Service→Podという流れをたどる。IstioのKialiアドオンツールを使うと、マイクロサービスの状況をダッシュボードで確認できる。
  • 「エンジニアも知っておきたい法律知識」
    • 個人情報の定義。氏名や生年月日など、特定の個人を識別できる場合、氏名や生年月日の部分のみならず、氏名や生年月日を含む「情報全体」が個人情報に該当。個人情報にあたるかどうかと、公開情報かどうか・プライバシー性があるかどうかは関係がない。
    • 他の情報と容易に照合できることによって特定の個人を識別できる、つまりDB A(個人情報)とDB B(氏名等を削除したもの)をキーなどの照合で容易にできていると、「容易照合性がある」ものとしてBも個人情報。
      • Bだけを第三者に提供する場合、第三者側は個人の識別はできない。しかしAは依然として容易照合性があるため、「Aは個人情報を第三者に提供した」と見なし、本人同意が必要。
    • 顔や指紋のようなデータ、あるいはパスポート番号や運転免許証番号などの法令で具体的に定められた「個人識別符号」を含む情報は個人情報。携帯電話・クレカ番号・クッキー・広告IDは個人識別符号ではない、が氏名や生年月日といった情報と併せて管理されていたら識別子を含めて個人情報。
  • SD Staff Room
    • 目次下部の本文デザインも併せて毎回ここも拝見しているのだが、池本さんの肩書きがとうとう猫編集長になってしまった…。