<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Notes - 64p.org</title>
<link>https://64p.org/notes/</link>
<atom:link href="https://64p.org/notes/rss.xml" rel="self" type="application/rss+xml" />
<description>ちょっと調べたことや検証結果を、AIの力も借りながらメモしていくコーナーです。</description>
<language>ja</language>
<lastBuildDate>Sat, 26 Sep 2026 08:03:40 +0900</lastBuildDate>
<item>
<title>Xoshiro256**</title>
<link>https://64p.org/notes/xoshiro256.html</link>
<guid isPermaLink="true">https://64p.org/notes/xoshiro256.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>Xoshiro256**</h1>

<p>David BlackmanとSebastiano Vignaが2018年に設計した疑似乱数生成器(PRNG)。Xorshift系列(XORとビットシフトの組み合わせで状態を更新するLFSRベースの高速な生成器群)の精神的後継にあたる。名前は各ラウンドを構成する3つの基本操作、XOR・SHIft・ROtateに由来する。</p>

<h2>仕組み</h2>

<p>256bit(64bit×4ワード)の内部状態を持つ。各ラウンドで、状態配列の各ワードを別のワードとXORし、シフトした値を次の要素にXORし、最後のワードをローテートする、という操作を経て次の状態に遷移する。状態遷移関数自体はGF(2)上で線形だが、出力段に非線形なスクランブル関数(名前の"**&ldquo;は出力に2回の乗算を使うスクランブル方式を表す)を挟むことで、単純な代数攻撃を防いでいる。</p>

<h2>周期と並列化</h2>

<p>周期は2<sup>256</sup> − 1。2<sup>128</sup>刻みでジャンプ可能なため、独立した部分系列を多数切り出して並列計算に使える点は<a href="https://64p.org/notes/philox.html">Philox</a>と共通するが、Philoxが「カウンタ+鍵」から無記憶に出力を計算するのに対し、Xoshiro256**は状態を逐次更新しながらジャンプ操作で系列を分割する設計。</p>

<h2><a href="https://64p.org/notes/pseudorandom-number-generator.html">疑似乱数生成器</a>の中での位置づけ</h2>

<p><a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a>の後継世代の一つで、<a href="https://64p.org/notes/pcg.html">PCG</a>と並び高速・高品質・小さな状態サイズを両立する現代的なPRNG。設計思想はXorshift系列の発展形(XOR+shift+rotate)であり、LCG+permutationの<a href="https://64p.org/notes/pcg.html">PCG</a>、カウンタベースの<a href="https://64p.org/notes/philox.html">Philox</a>とはアプローチが異なる。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/random.html">#random</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://bashtage.github.io/randomgen/bit_generators/xoshiro256.html">Xoshiro256** - RandomGen</a></li>
<li><a href="https://prng.di.unimi.it/">A PRNG shootout</a></li>
<li><a href="https://www.pistack.xyz/posts/2026-06-19-prng-algorithm-libraries-xoshiro-pcg-splitmix-mersenne-twister/">Open-Source PRNG Algorithm Libraries: Xoshiro vs PCG vs SplitMix vs Mersenne Twister | Pi Stack</a></li>
</ul>

]]></description>
</item>
<item>
<title>typescript-eslint</title>
<link>https://64p.org/notes/typescript-eslint.html</link>
<guid isPermaLink="true">https://64p.org/notes/typescript-eslint.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>typescript-eslint</h1>

<p>TypeScriptコードを<a href="https://64p.org/notes/eslint.html">ESLint</a>でlintできるようにするツール群（パーサーとプラグインのモノレポプロジェクト）。ESLint本体はJavaScriptのみを解釈するため、TypeScript対応はこのプロジェクトがプラグインとして担っている。 <a class="note-tag" href="https://64p.org/notes/tags/javascript.html">#javascript</a> <a class="note-tag" href="https://64p.org/notes/tags/typescript.html">#typescript</a></p>

<h2>TSLintからの移行</h2>

<p>かつてTypeScriptにはTSLintという専用リンターがあったが、2019年に非推奨（deprecated）となり、公式にtypescript-eslintへの移行が推奨された。以降、JavaScript/TypeScript両方のlintをESLintエコシステムに一本化するのが標準になっている。移行用に設定変換ツール（tslint-to-eslint-config）も提供された。</p>

<h2>type-aware linting（typed linting）</h2>

<p>typescript-eslintの特徴的な機能が、TypeScriptコンパイラの型情報を使ってコードを検査する「型認識lint（type-aware linting / typed linting）」。型情報がないと検出できない問題（例: Promiseのawait忘れ）を検出できる。ただしlint前にTypeScriptによるプロジェクトのビルド相当の処理が必要になるため、性能上のコストがかかる。</p>

<p><a href="https://64p.org/notes/biome.html">Biome</a> v2が「TypeScriptコンパイラに依存しない型認識lint」を打ち出しているのは、このコストへの対案という文脈。</p>

<h2><a href="https://64p.org/notes/javascript-linters-formatters.html">JavaScriptのリンター・フォーマッター</a>の中での位置づけ</h2>

<p><a href="https://64p.org/notes/eslint.html">ESLint</a>のプラグイン機構の上に成立している拡張であり、ESLintエコシステムの代表例。<a href="https://64p.org/notes/biome.html">Biome</a>のリンターが搭載するルールの由来元のひとつでもある。</p>

<h2>出典</h2>

<ul>
<li><a href="https://typescript-eslint.io/">typescript-eslint</a></li>
<li><a href="https://typescript-eslint.io/users/what-about-tslint/">What About TSLint? | typescript-eslint</a></li>
<li><a href="https://typescript-eslint.io/blog/typed-linting/">Typed Linting: The Most Powerful TypeScript Linting Ever | typescript-eslint</a></li>
</ul>

]]></description>
</item>
<item>
<title>テイラー展開</title>
<link>https://64p.org/notes/taylor-series.html</link>
<guid isPermaLink="true">https://64p.org/notes/taylor-series.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>テイラー展開</h1>

<p><a class="note-tag" href="https://64p.org/notes/tags/math.html">#math</a></p>

<p>関数を、1点での<a href="https://64p.org/notes/derivative.html">微分</a>係数の情報だけを使って多項式（冪級数）で表現する手法。</p>

<div class="math-display">
f(x) = \sum_{n=0}^{\infty} \frac{f^{(n)}(a)}{n!} (x-a)^n = f(a) + f'(a)(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \cdots
</div>


<p>点 <span class="math-inline">a</span> を中心に展開したものをテイラー級数、特に <span class="math-inline">a = 0</span> を中心にしたものを<strong>マクローリン級数</strong>と呼ぶ。</p>

<h2>直感 — 接線近似の高次版</h2>

<p><a href="https://64p.org/notes/derivative.html">微分</a>による一次近似 <span class="math-inline">f(a+h) \approx f(a) + f'(a)h</span>（接線で代用する）の精度を、2次・3次…の項を足して上げていったもの。1次で「傾き」、2次で「曲がり具合」、と高階の導関数が形の情報を順に補っていき、次数を上げるほど元の関数に近づく。</p>

<h2>剰余項と収束</h2>

<p>有限次で打ち切った<strong>テイラー多項式</strong>と元の関数との差が剰余項 <span class="math-inline">R_n(x)</span>。剰余項が <span class="math-inline">n \to \infty</span> で 0 に収束する範囲でのみ、テイラー級数は元の関数に一致する。<span class="math-inline">e<sup>x</sup></span>, <span class="math-inline">\sin x</span>, <span class="math-inline">\cos x</span> は全実数で収束する代表例。</p>

<div class="math-display">
e^x = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots
</div>


<h2>用途</h2>

<ul>
<li><strong>数値計算</strong> — 関数電卓やライブラリが <span class="math-inline">\sin</span> や <span class="math-inline">e<sup>x</sup></span> を計算する際の基礎（実装では精度最適化した多項式近似が使われるが、発想の原点）</li>
<li><strong>物理の近似</strong> — 「<span class="math-inline">\theta</span> が小さいとき <span class="math-inline">\sin\theta \approx \theta</span>」のような微小量近似は、テイラー展開を1次で打ち切ったもの</li>
<li><strong>オイラーの公式</strong> — <span class="math-inline">e^{ix}</span>, <span class="math-inline">\cos x</span>, <span class="math-inline">\sin x</span> のマクローリン級数を見比べると <span class="math-inline">e^{ix} = \cos x + i \sin x</span> が導ける。<a href="https://64p.org/notes/fourier-transform.html">フーリエ変換</a>の核 <span class="math-inline">e^{-i\omega t}</span> の背後にある関係式</li>
</ul>


<h2>出典</h2>

<ul>
<li><a href="https://mathresearch.utsa.edu/wiki/index.php?title=Taylor_and_Maclaurin_Series">Taylor and Maclaurin Series - UTSA</a></li>
<li><a href="https://courses.lumenlearning.com/calculus2/chapter/taylors-theorem-with-remainder/">Taylor&rsquo;s Theorem with Remainder and Convergence - Lumen Learning</a></li>
<li><a href="https://www.parabola.unsw.edu.au/sites/default/files/2025-04/vol61_no1_7.pdf">An introduction to Taylor series and their applications - Parabola (UNSW)</a></li>
</ul>

]]></description>
</item>
<item>
<title>SynthID-Text</title>
<link>https://64p.org/notes/synthid-text.html</link>
<guid isPermaLink="true">https://64p.org/notes/synthid-text.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>SynthID-Text</h1>

<p><a class="note-tag" href="https://64p.org/notes/tags/llm.html">#llm</a> <a class="note-tag" href="https://64p.org/notes/tags/ai.html">#ai</a> <a class="note-tag" href="https://64p.org/notes/tags/security.html">#security</a> <a class="note-tag" href="https://64p.org/notes/tags/watermarking.html">#watermarking</a> <a class="note-tag" href="https://64p.org/notes/tags/google.html">#google</a></p>

<p>Google DeepMind による<a href="https://64p.org/notes/llm-text-watermarking.html">LLMテキスト電子透かし</a>の本番実装。論文 &ldquo;Scalable watermarking for identifying large language model outputs&rdquo; は Nature（2024-10）に掲載された。<strong>生成テキスト透かしを大規模本番運用した初の事例</strong>で、Gemini / Gemini Advanced 上で数百万ユーザー規模で稼働した。</p>

<h2>Tournament sampling</h2>

<p>中核のアルゴリズム。次トークンを決めるときに:</p>

<ol>
<li>元の分布から候補トークンを複数サンプリングする</li>
<li>候補をペアにして、秘密鍵由来の疑似乱数関数（PRF）のスコアが大きい方を勝ち残らせる</li>
<li>これをL層のトーナメントとして繰り返し、最後に残ったトークンを出力する</li>
</ol>


<p>基礎に本物のサンプリングが残っているため「同じプロンプトでも毎回違う応答」という多様性が保たれる。Gumbel-max系のdistortion-free手法が抱える出力の決定化問題を回避しつつ、設定次第で:</p>

<ul>
<li><strong>非歪曲（non-distortionary）</strong>: 出力分布を保存し品質劣化なし</li>
<li><strong>歪曲（distortionary）</strong>: 品質を少し犠牲にして検出力を上げる</li>
</ul>


<p>の両モードを選べる。論文では両カテゴリで既存手法（KGW系・Gumbel系）より検出力が高いことを示した。</p>

<h2>実運用上の特徴</h2>

<ul>
<li>学習には一切手を入れず、サンプリング手順だけを差し替える</li>
<li>検出はLLM本体を使わず軽量に実行できる</li>
<li>約2,000万件の本番トラフィックでの人間フィードバック評価で品質劣化なしを確認</li>
<li>実装はオープンソース化されており、Hugging Face Transformers にも組み込まれている</li>
</ul>


<h2><a href="https://64p.org/notes/llm-text-watermarking.html">LLMテキストの電子透かし</a>の中での位置づけ</h2>

<p>ロジット操作型（KGW法）とサンプリング置換型（Gumbel-max）の長所を統合した実用システム。ただしトークン表層の偏りに依存する点は変わらず、強い言い換え・翻訳への耐性は限定的。</p>

<h2>出典</h2>

<ul>
<li><a href="https://www.nature.com/articles/s41586-024-08025-4">Scalable watermarking for identifying large language model outputs (Nature, 2024)</a></li>
<li><a href="https://arxiv.org/abs/2603.03410">On Google&rsquo;s SynthID-Text LLM Watermarking System: Theoretical Analysis and Empirical Validation (2026)</a> — 第三者による理論解析</li>
</ul>

]]></description>
</item>
<item>
<title>Swagger</title>
<link>https://64p.org/notes/swagger.html</link>
<guid isPermaLink="true">https://64p.org/notes/swagger.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>Swagger</h1>

<p>もともとは<a href="https://64p.org/notes/openapi.html">OpenAPI</a>仕様そのものの名前だったが、2016年のOpenAPI Initiativeへの寄贈・改称後は、SmartBearが保守・提供するAPI開発ツール群のブランド名として使われている。</p>

<h2>創始者</h2>

<p>2011年、辞書サイトWordnikの技術共同創業者Tony TamがSwagger APIプロジェクトを作成した。WordnikのAPI開発において、APIドキュメントの自動生成とクライアントSDK生成の手間が大きな課題になっていたことが動機。</p>

<h2>仕様としてのSwagger: Swagger 2.0</h2>

<p>OpenAPI Initiativeへ寄贈される前の最終仕様バージョンが2014年リリースのSwagger 2.0で、今も"Swagger 2.0"あるいは"OpenAPI 2.0"と呼ばれる。詳しいバージョン変遷は<a href="https://64p.org/notes/openapi.html">OpenAPI</a>を参照。</p>

<h2>ブランドとしてのSwagger: SmartBearのツール群</h2>

<p>現在SmartBearが保守・開発するOSSツール群にも"Swagger"の名が残っている。</p>

<ul>
<li><strong><a href="https://64p.org/notes/swagger-ui-editor.html">Swagger UI / Swagger Editor</a></strong> — API可視化・設計エディタ</li>
<li><strong>Swagger Codegen</strong> — APIクライアントSDK・サーバースタブ生成の元祖ツール。OpenAPI 3.0に対応し、現在もOSSとして更新が続いている。<a href="https://64p.org/notes/openapi-generator.html">openapi-generator</a>は2018年にこのプロジェクトからコミュニティ主導でforkされたもの</li>
<li><strong>SwaggerHub</strong> — 商用のAPI設計・コラボレーションプラットフォーム。エディタでの入力補完・スタイルバリデーターに加え、API分析・監視・テスト・バージョン管理・APIモッキング、共通OAS構文を複数API間で再利用する「Domains」機能などを統合している</li>
</ul>


<h2>名称の整理</h2>

<p>「OpenAPI」が仕様そのものを指し、「Swagger」がSmartBearのツール群・製品ブランドを指す、という使い分けが現在の一般的な理解。<a href="https://64p.org/notes/openapi-tooling.html">OpenAPI関連ツールエコシステム</a>の中では、Swagger系ツールはSmartBear傘下（買収後は<a href="https://64p.org/notes/spectral.html">Spectral</a>・<a href="https://64p.org/notes/prism-mock-server.html">Prism</a>も同傘下）という位置づけになる。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/openapi.html">#openapi</a> <a class="note-tag" href="https://64p.org/notes/tags/api-documentation.html">#api-documentation</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Swagger_(software">Swagger (software) - Wikipedia</a>)</li>
<li><a href="https://platform.softwareone.com/product/swagger-codegen/PCP-3383-6551">Swagger Codegen - SoftwareOne Marketplace</a></li>
<li><a href="https://www.getapp.com/it-management-software/a/swaggerhub/">SwaggerHub - GetApp</a></li>
</ul>

]]></description>
</item>
<item>
<title>疑似乱数生成器</title>
<link>https://64p.org/notes/pseudorandom-number-generator.html</link>
<guid isPermaLink="true">https://64p.org/notes/pseudorandom-number-generator.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>疑似乱数生成器</h1>

<p>決定的なアルゴリズムによって、統計的にはランダムに見える数列を生成する仕組み(PRNG)。設計思想・状態の持ち方・並列化のしやすさで系統立てて整理できるため、代表的なアルゴリズムをまとめるハブノート。</p>

<h2>状態逐次更新型</h2>

<ul>
<li><a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a> — 1997年発表。624×32bitの大きな内部状態を「twist」操作で更新する。長らくの標準だったが、LinearComp検定の失敗など弱点も知られる。</li>
<li><a href="https://64p.org/notes/pcg.html">PCG</a> — 線形合同法(LCG)に出力permutationを加えた設計。状態サイズが小さく(典型64bit)、Mersenne Twisterより高速。</li>
<li><a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a> — Xorshift系列の後継。XOR・シフト・ローテートで256bit状態を更新し、非線形な出力スクランブルを加える。2<sup>128</sup>刻みでジャンプ可能。</li>
</ul>


<h2>カウンタベース型</h2>

<ul>
<li><a href="https://64p.org/notes/philox.html">Philox</a> — 「カウンタ+鍵」のみを状態として持ち、暗号学的ハッシュに似た関数で直接出力を計算する無記憶な設計。任意のインデックスに直接ジャンプできるため並列計算との親和性が最も高く、TensorFlowのデフォルト生成器に採用。</li>
</ul>


<h2>選び方の傾向</h2>

<p>状態逐次更新型(Mersenne Twister/PCG/Xoshiro256<strong>)は汎用用途で使われ、中でもPCG・Xoshiro256</strong>はMersenne Twisterより高速・高品質な後継として置き換えが進んでいる。カウンタベース型のPhiloxは、GPU/分散環境で「どのスレッドがどの範囲の乱数を生成するか」を厳密に制御したい場面(大規模並列シミュレーション、機械学習フレームワーク)で選ばれる。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/random.html">#random</a> <a class="note-tag" href="https://64p.org/notes/tags/moc.html">#moc</a></p>
]]></description>
</item>
<item>
<title>Philox</title>
<link>https://64p.org/notes/philox.html</link>
<guid isPermaLink="true">https://64p.org/notes/philox.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>Philox</h1>

<p>カウンタベース(counter-based)方式の疑似乱数生成器(PRNG)。2011年にJohn Salmonら(D. E. Shaw Research)が発表した<a href="https://www.deshawresearch.com/resources_random123.html">Random123</a>ライブラリに含まれる生成器の一つ。</p>

<h2>仕組み</h2>

<p>一般的なPRNGが内部状態を逐次更新しながら次の乱数を作るのに対し、Philoxは「カウンタ」と「鍵(key)」という2つの値だけを状態として持ち、それを暗号学的ハッシュに似た(が弱い)ブロック暗号風の関数に通して直接出力を得る。カウンタは乱数を1つ生成するたびに1ずつインクリメントされ、鍵は生成される数列そのものを決定する。異なる鍵を使えば別々の(統計的に独立とみなせる)数列が得られる。</p>

<p>暗号用途には向かないとされる一方、GPU上でCrush系の統計検定に耐える生成器としては最速級と言われている。</p>

<h2>並列計算との親和性</h2>

<p>カウンタ方式であるため、必要な乱数の個数が分かっていれば生成サイクルの任意の位置に直接ジャンプできる。<code>jumped</code>メソッドで2<sup>128</sup>個生成した状態相当に一気に進める、といった操作も可能。<a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a>や<a href="https://64p.org/notes/pcg.html">PCG</a>、<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>のように状態を逐次更新する系列だとストリームの分割・並列化が難しいのに対し、Philoxはインデックスさえ決まれば各スレッド/GPUコアが独立に計算できる。</p>

<p>この特性から、GPU/大規模並列計算との親和性が高く、TensorFlowのデフォルト乱数生成器として採用されている。NumPyの<code>numpy.random.Philox</code>などでも利用可能。</p>

<h2><a href="https://64p.org/notes/pseudorandom-number-generator.html">疑似乱数生成器</a>の中での位置づけ</h2>

<p>状態を持たず「カウンタ+鍵→出力」という無記憶な設計思想を取る点で、<a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a>・<a href="https://64p.org/notes/pcg.html">PCG</a>・<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>といった状態逐次更新型の系列とは根本的に異なるアプローチ。並列化のしやすさを最優先する用途(GPU計算、分散シミュレーション)で選ばれる。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/random.html">#random</a> <a class="note-tag" href="https://64p.org/notes/tags/parallel-computing.html">#parallel-computing</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://numpy.org/doc/stable/reference/random/bit_generators/philox.html">Philox counter-based RNG — NumPy Manual</a></li>
<li><a href="https://bashtage.github.io/randomgen/devel/bit_generators/philox.html">Philox Counter-based RNG - RandomGen</a></li>
</ul>

]]></description>
</item>
<item>
<title>PCG (Permuted Congruential Generator)</title>
<link>https://64p.org/notes/pcg.html</link>
<guid isPermaLink="true">https://64p.org/notes/pcg.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>PCG (Permuted Congruential Generator)</h1>

<p>線形合同法(LCG)を状態遷移関数として使い、出力段に「permutation(並べ替え)」処理を加えることでLCGの弱点を補う設計の疑似乱数生成器(PRNG)。<a href="https://www.pcg-random.org/index.html">PCG, A Family of Better Random Number Generators</a>として公開されている。</p>

<h2>仕組み</h2>

<p>単純なLCGは下位ビットの周期が短い・統計的な規則性が現れやすいといった弱点を持つ。PCGはLCGの生の出力をそのまま返すのではなく、下位ビットを捨てたうえで追加のpermutation関数を通して出力することで、内部状態よりもはるかにランダムに見える出力を作る。</p>

<h2>状態サイズと性能</h2>

<p>状態サイズは典型的に64bitと、<a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a>(624×32bit)や<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>(256bit)と比べて小さい。32bit出力の生成速度でMersenne Twisterの2〜5倍(35Gb/s超 vs MTの13〜27Gb/s)というベンチマークが報告されており、Mersenne TwisterからPCGへ置き換えることでシミュレーションの実行時間が20〜40%短縮された事例もある。</p>

<p><a href="https://64p.org/notes/philox.html">Philox</a>と同様、暗号強度は主張しない「medium-strength」の生成器に分類される。</p>

<h2><a href="https://64p.org/notes/pseudorandom-number-generator.html">疑似乱数生成器</a>の中での位置づけ</h2>

<p><a href="https://64p.org/notes/mersenne-twister.html">Mersenne Twister</a>の弱点(状態サイズの大きさ、LinearComp検定の失敗)を踏まえた後継世代の一つ。設計思想は「LCG+出力permutation」というシンプルなもので、<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>(XOR+shift+rotate)や<a href="https://64p.org/notes/philox.html">Philox</a>(カウンタベース)とは異なるアプローチで高速・高品質を両立している。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/random.html">#random</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://www.pcg-random.org/index.html">PCG, A Family of Better Random Number Generators</a></li>
<li><a href="https://grokipedia.com/page/Permuted_congruential_generator">Permuted congruential generator — Grokipedia</a></li>
<li><a href="https://www.pistack.xyz/posts/2026-06-19-prng-algorithm-libraries-xoshiro-pcg-splitmix-mersenne-twister/">Open-Source PRNG Algorithm Libraries: Xoshiro vs PCG vs SplitMix vs Mersenne Twister | Pi Stack</a></li>
</ul>

]]></description>
</item>
<item>
<title>OpenJS Foundation</title>
<link>https://64p.org/notes/openjs-foundation.html</link>
<guid isPermaLink="true">https://64p.org/notes/openjs-foundation.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>OpenJS Foundation</h1>

<p>JavaScriptエコシステムのOSSプロジェクトをホストする非営利財団。2019年3月にNode.js FoundationとJS Foundationが合併して発足した。Linux Foundation傘下のサブファウンデーションとして運営されている。 <a class="note-tag" href="https://64p.org/notes/tags/javascript.html">#javascript</a> <a class="note-tag" href="https://64p.org/notes/tags/oss.html">#oss</a></p>

<h2>系譜</h2>

<p>複数の財団の合併を重ねてできた組織。</p>

<div class="mermaid">
graph TD
    jquery["jQuery Foundation (2012)"] --&gt; jsf["JS Foundation (2016)"]
    dojo["Dojo Foundation"] --&gt; jsf
    nodejs["Node.js Foundation (2015)"] --&gt; openjs["OpenJS Foundation (2019)"]
    jsf --&gt; openjs
</div>


<h2>ホストするプロジェクト</h2>

<p>Node.js・jQuery・webpack・Appium・Node-RED・<a href="https://64p.org/notes/eslint.html">ESLint</a>・<a href="https://64p.org/notes/electron.html">Electron</a>など、約38のOSSプロジェクトをホストする（2025年時点）。設立時のメンバーにはGoogle・Microsoft・IBM・PayPal・GoDaddy・Joyentなどが名を連ねる。ドイツのSovereign Tech Fundから80万ユーロ超の資金提供を受けるなど、公的資金によるOSS支援の受け皿にもなっている。</p>

<h2>役割</h2>

<p>特定企業に属さない中立的な組織としてプロジェクトの商標・ガバナンスを引き受け、JavaScriptエコシステム全体の持続的な成長を支えることを使命とする。個人が始めたプロジェクトが広く使われるようになったとき、その資産（商標など）と運営を引き継ぐ受け皿として機能している（例: <a href="https://64p.org/notes/eslint.html">ESLint</a>は2016年にjQuery Foundationに参加し、合併を経て現在はOpenJS Foundation傘下）。</p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/OpenJS_Foundation">OpenJS Foundation - Wikipedia</a></li>
<li><a href="https://www.linuxfoundation.org/press/press-release/node-js-foundation-and-js-foundation-merge-to-form-openjs-foundation">Node.js Foundation and JS Foundation Merge to Form OpenJS Foundation - Linux Foundation</a></li>
<li><a href="https://openjsf.org/">OpenJS Foundation</a></li>
</ul>

]]></description>
</item>
<item>
<title>Network Namespace (netns)</title>
<link>https://64p.org/notes/network-namespace.html</link>
<guid isPermaLink="true">https://64p.org/notes/network-namespace.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>Network Namespace (netns)</h1>

<p>Linuxカーネルの機能で、プロセスグループごとに独立したネットワークスタックを持たせる分離技術。カーネル内部では各namespaceインスタンスが<code>struct net</code>で表現される。プロセス・ファイルシステム・IPCなどを分離する他のnamespace種別と並ぶ、Linux namespaces機構の一種。<a href="https://64p.org/notes/cgroups.html">cgroups（control groups）</a>によるリソース制御と組み合わせて<a href="https://64p.org/notes/lxc.html">LXC</a>などの軽量仮想化の基盤にもなっている。 <a class="note-tag" href="https://64p.org/notes/tags/network.html">#network</a> <a class="note-tag" href="https://64p.org/notes/tags/linux.html">#linux</a> <a class="note-tag" href="https://64p.org/notes/tags/kernel.html">#kernel</a></p>

<h2>namespaceごとに独立して管理されるもの</h2>

<ul>
<li>ネットワークインターフェース（lo, eth0など）</li>
<li>ルーティングテーブル（IPv4/IPv6）</li>
<li>iptables/nftablesのファイアウォール設定</li>
<li>netfilterの接続追跡状態</li>
<li>Unixドメインソケットの名前空間</li>
<li>ポート番号空間（0-65535）</li>
<li><code>/proc/net/</code>以下のビュー</li>
</ul>


<p>初期化時に<code>pernet_operations</code>フックを通じて、各サブシステムがper-namespace状態を初期化する。</p>

<h2>管理コマンド: ip netns</h2>

<pre><code class="sh">ip netns add ns1                        # 名前空間を作成
ip netns exec ns1 &lt;cmd&gt;                  # 名前空間内でコマンド実行
ip link set &lt;iface&gt; netns ns1            # 既存インターフェースを移動
ip netns del ns1                         # 削除
</code></pre>

<h2>veth pairによる接続</h2>

<p>異なるnamespace同士やnamespaceとホストを繋ぐ標準的な手段が<strong>veth pair</strong>（仮想Ethernetペア）。片方に入れたフレームがもう片方から出てくる「パイプ」のように振る舞う。ペアの一端をnamespace Aに、もう一端をnamespace Bやホストに配置して接続する。<a href="https://64p.org/notes/linux-virtual-network-lab.html">実際に構築した例</a>では、veth pairで複数のnamespaceを<a href="https://64p.org/notes/linux-bridge.html">Linuxブリッジ</a>に接続した。</p>

<h2>unprivileged user namespaceとの組み合わせ</h2>

<p><code>unshare --user --map-root-user --net</code>のようにuser namespaceと組み合わせることで、sudoなしでもnetwork namespaceを作成・操作できる。ただし作成したnamespaceはホストの実NICには触れられない。</p>

<h2>出典</h2>

<ul>
<li><a href="https://kernel-internals.org/net/net-namespaces/">Network Namespaces - Linux Kernel Internals</a></li>
<li><a href="https://www.commandinline.com/linux-network-namespaces-guide/">Linux Network Namespaces: Isolate Network Stacks | Command in Line</a></li>
</ul>

]]></description>
</item>
<item>
<title>Mersenne Twister</title>
<link>https://64p.org/notes/mersenne-twister.html</link>
<guid isPermaLink="true">https://64p.org/notes/mersenne-twister.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>Mersenne Twister</h1>

<p>1997年に松本眞・西村拓士が発表した汎用疑似乱数生成器(PRNG)。名前は周期が2<sup>19937</sup> − 1というメルセンヌ素数(2<sup>p</sup> − 1の形の素数)であることに由来する。</p>

<h2>仕組み</h2>

<p>内部状態として624個の32bit整数からなる配列を持つ。乱数を1つ要求されるたびに状態配列から1要素を取り出して出力用の変換を施し、624個出力し終えるごとに「twist」と呼ばれる操作で状態配列全体を更新する(アルゴリズム名の由来)。1回の生成コストはO(1)。</p>

<h2>統計的品質と評価の変化</h2>

<p>長らく「強いPRNG」(長い周期と統計的に一様な分布)の代表例として扱われ、Python3の<code>random</code>モジュールをはじめ多くの言語・環境の標準乱数生成器に採用されてきた。一方で、TestU01のLinearComp検定(80番・81番)には一貫して落ちることが知られており、線形性に起因する弱点を持つ。近年は<a href="https://64p.org/notes/pcg.html">PCG</a>や<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>など、より高速かつ統計的品質の高い後継世代への置き換えが進んでいる。</p>

<h2>内部状態サイズと並列化</h2>

<p>内部状態が624×32bit(約2,503バイト)と大きく、<a href="https://64p.org/notes/pcg.html">PCG</a>(典型64bit)や<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>(256bit)と比べてコピーコストが高い。状態を逐次更新する設計のため、<a href="https://64p.org/notes/philox.html">Philox</a>のようにストリームの任意位置へ直接ジャンプすることはできず、並列計算での分割利用には工夫が要る。</p>

<h2><a href="https://64p.org/notes/pseudorandom-number-generator.html">疑似乱数生成器</a>の中での位置づけ</h2>

<p>CBRNG以前の世代を代表する、状態逐次更新型PRNGの標準的な選択肢だった。現在は速度・状態サイズ・並列化のしやすさの面で<a href="https://64p.org/notes/pcg.html">PCG</a>・<a href="https://64p.org/notes/xoshiro256.html">Xoshiro256**</a>・<a href="https://64p.org/notes/philox.html">Philox</a>といった後継世代に置き換わりつつある。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/random.html">#random</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Mersenne_Twister">Mersenne Twister — Wikipedia</a></li>
<li><a href="https://www.pistack.xyz/posts/2026-06-19-prng-algorithm-libraries-xoshiro-pcg-splitmix-mersenne-twister/">Open-Source PRNG Algorithm Libraries: Xoshiro vs PCG vs SplitMix vs Mersenne Twister | Pi Stack</a></li>
</ul>

]]></description>
</item>
<item>
<title>JSHint</title>
<link>https://64p.org/notes/jshint.html</link>
<guid isPermaLink="true">https://64p.org/notes/jshint.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>JSHint</h1>

<p>Anton Kovalyov氏が2011年に<a href="https://64p.org/notes/jslint.html">JSLint</a>をフォークして作ったJavaScriptリンター。フォークの動機は「JSLintは不快なほどオピニオン化していた（uncomfortably opinionated）」というもので、JSLintが許さなかったルールのカスタマイズをコミュニティ主導で可能にした。 <a class="note-tag" href="https://64p.org/notes/tags/javascript.html">#javascript</a></p>

<h2>ライセンス問題の継承と解消</h2>

<p>フォーク元のJSLint由来のコードに「Good, not Evil」条項（詳細は<a href="https://64p.org/notes/jslint.html">JSLint</a>参照）が残っていたため、JSHintも長年Free Software Foundationから非フリー扱いされていた。2020年8月に該当コードをすべて置き換えて完全なMITライセンスとなり、問題が解消された。</p>

<h2><a href="https://64p.org/notes/javascript-linters-formatters.html">JavaScriptのリンター・フォーマッター</a>の中での位置づけ</h2>

<p>JSリンター系譜の中間世代。<a href="https://64p.org/notes/jslint.html">JSLint</a>の「設定不可」への反発から生まれたが、独自ルールの追加はできず、その制約への不満から<a href="https://64p.org/notes/eslint.html">ESLint</a>が生まれた。「設定可能」（JSHint）から「プラガブル」（ESLint）への進化の途中段階といえる。</p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/JSHint">JSHint - Wikipedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/JSLint">JSLint - Wikipedia</a></li>
</ul>

]]></description>
</item>
<item>
<title>命令セットアーキテクチャ(ISA)</title>
<link>https://64p.org/notes/instruction-set-architecture.html</link>
<guid isPermaLink="true">https://64p.org/notes/instruction-set-architecture.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>命令セットアーキテクチャ(ISA)</h1>

<p>CPUのプログラム可能なインターフェースを定義する抽象モデル。ソフトウェアがハードウェアとどう相互作用するかを規定し、命令・データ型・レジスタ・アドレッシングモード・仮想メモリ・メモリ一貫性機構などを含む。ARM自身の用語集も「プロセッサのハードウェアとその上で動くソフトウェアの間の抽象インターフェース」と定義しており、ハードウェアとソフトウェアの境界を成すという位置づけで一致する。</p>

<h2>仕様と実装の違い</h2>

<p>ISAはマイクロアーキテクチャ(特定プロセッサでの実装技法)と明確に区別される。異なるマイクロアーキテクチャが同一のISAを共有できる点が重要で、例えばIntel PentiumとAMD Athlonは内部設計が全く異なるが、ほぼ同一のx86 ISAを実装している。</p>

<h2>CISCとRISCの対立</h2>

<p>「CISC」という語は「RISCに対する対比として遡及的に作られた」呼称。1970年代半ば、IBM Watson研究所のJohn CockeらによるIBM 801プロジェクトがRISC思想の先駆けとなり、1980年代前半にUC BerkeleyのDavid PattersonとDavid Ditzelが命令を単純化し固定長・レジスタ間演算中心の設計を提唱、論文"The Case for the Reduced Instruction Set Computer"(1980年)で"RISC"という語を作った。1980年代半ばにはDECの試算で「RISCの価格性能比はCISCの最大2倍」との評価が出て、SunがMotorola 68000からSPARCへ移行するなど業界に影響を与えた。</p>

<p><a href="https://64p.org/notes/riscv-design-criticism.html">RISC-Vの設計批判</a>で論じられている「オプション性」「命令エンコーディング」の問題は、いずれもこのRISC系ISA設計における一般的な論点(拡張の持たせ方、命令長の固定/可変)の具体例にあたる。</p>

<h2>オプショナルな命令セット拡張</h2>

<p>ISAは「命令や機能を追加して拡張可能であり、拡張版の実装は拡張前のコードも実行できるが、拡張命令を使うコードは対応実装でしか動かない」という一般原則がある。実例:</p>

<ul>
<li><strong>x86</strong>: SSE/AVXはCPUID命令でランタイム検出する拡張機能。</li>
<li><strong>ARM</strong>: NEON(SIMD拡張)はARMv7-A/RおよびArmv8-R AArch64でオプション扱い。</li>
<li><strong>RISC-V</strong>: ベース整数ISA(RV32I/RV64Iなど)にM(乗除算)・A(アトミック)・F/D(浮動小数点)などの標準拡張を任意に組み合わせるモジュール式設計。IMAFD一式は"G"と略称される。</li>
</ul>


<h2>命令エンコーディングのトレードオフ</h2>

<p>固定長命令は「キャッシュラインや仮想メモリページ境界をまたぐかの判定が不要」など単純で高速化しやすい一方、x86は1〜15バイトの可変長命令(プレフィックス・opcode・ModRM・SIB・displacement・immediateの可変構成)で、スーパースカラ実行時の命令境界検出が課題となる。圧縮命令セットの例として、ARM Thumbは32ビット命令2個を1ワードにパックしデコード時に展開する方式、RISC-VのC拡張(16ビット圧縮命令)は32ビット命令と自由に混在させ、コードサイズを25〜30%削減する。</p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Instruction_set_architecture">Wikipedia: Instruction set architecture</a></li>
<li><a href="https://www.arm.com/glossary/isa">ARM: What is Instruction Set Architecture (ISA)?</a></li>
<li><a href="https://en.wikipedia.org/wiki/Complex_instruction_set_computer">Wikipedia: Complex instruction set computer</a></li>
<li><a href="https://www.cs.utexas.edu/~fussell/courses/cs352h/papers/risc.pdf">Patterson &amp; Ditzel, &ldquo;The Case for the Reduced Instruction Set Computer&rdquo; (1980)</a></li>
<li><a href="https://www.arm.com/technologies/neon">ARM: Neon</a></li>
<li><a href="https://docs.riscv.org/reference/isa/v2.2/riscv-spec.pdf">RISC-V ISA Manual — Standard Extensions</a></li>
<li><a href="https://docs.riscv.org/reference/isa/unpriv/c-st-ext.html">RISC-V &ldquo;C&rdquo; Extension for Compressed Instructions</a></li>
<li><a href="https://wiki.osdev.org/X86-64_Instruction_Encoding">OSDev Wiki: x86-64 Instruction Encoding</a></li>
</ul>


<p><a class="note-tag" href="https://64p.org/notes/tags/isa.html">#isa</a> <a class="note-tag" href="https://64p.org/notes/tags/cpu-architecture.html">#cpu-architecture</a></p>
]]></description>
</item>
<item>
<title>ICFPC (ICFP Programming Contest)</title>
<link>https://64p.org/notes/icfpc.html</link>
<guid isPermaLink="true">https://64p.org/notes/icfpc.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>ICFPC (ICFP Programming Contest)</h1>

<p>関数型プログラミングの国際会議 ICFP (International Conference on Functional Programming) の併設コンテストとして、1998年から毎年6〜7月頃に開催されている国際プログラミングコンテスト。結果はICFP会議の場で発表される。 <a class="note-tag" href="https://64p.org/notes/tags/competitive-programming.html">#competitive-programming</a> <a class="note-tag" href="https://64p.org/notes/tags/functional-programming.html">#functional-programming</a></p>

<p>名前が似ている <a href="https://64p.org/notes/acm-icpc.html">ICPC</a> とは別物で、性格もまったく違う。</p>

<h2>競技形式</h2>

<ul>
<li><strong>制限時間</strong>: 72時間。最初の24時間で締め切られる Lightning Division も併設される</li>
<li><strong>チーム人数</strong>: 無制限。参加費無料でインターネット経由で参加する</li>
<li><strong>使用言語</strong>: 完全に自由</li>
<li><strong>賞</strong>: 優勝チームには賞金ではなく、使用した言語が &ldquo;the programming tool of choice for discriminating hackers&rdquo; であると宣言される、いわゆる bragging rights（自慢する権利）が与えられる。言語・ツールの実力を示す場という側面が強い</li>
</ul>


<h2>問題の性格</h2>

<p><a href="https://64p.org/notes/acm-icpc.html">ICPC</a> のような整ったアルゴリズム問題の早解きではなく、毎年持ち回りの主催者が用意する一発ネタの大規模課題を72時間かけて攻略する総合戦。リバースエンジニアリング・最適化・謎解きなどの要素が混ざることが多い。</p>

<p>有名な回として、2006年のCMU主催回「The Cult of the Bound Variable」がある。仮想機械 UM-32 の仕様書とディスクイメージだけが渡され、VMを実装して起動すると架空のOS「UMIX」のログイン画面が現れ、その中に複数の課題と謎解きが仕込まれている、という凝った構成だった。365チーム・700人が少なくとも1つの課題を解いた。</p>

<h2>ICPCとの対比</h2>

<table>
<thead>
<tr>
<th> </th>
<th> [[acm-icpc|ICPC]] </th>
<th> ICFPC </th>
</tr>
</thead>
<tbody>
<tr>
<td> 主催母体 </td>
<td> ICPC Foundation（元ACM） </td>
<td> ICFP会議（ACM SIGPLAN） </td>
</tr>
<tr>
<td> 対象 </td>
<td> 大学生のみ（3人・PC1台） </td>
<td> 誰でも（人数無制限） </td>
</tr>
<tr>
<td> 時間 </td>
<td> 5時間 </td>
<td> 72時間 </td>
</tr>
<tr>
<td> 言語 </td>
<td> 指定言語のみ </td>
<td> 完全自由 </td>
</tr>
<tr>
<td> 性格 </td>
<td> アルゴリズム早解き </td>
<td> 大規模・謎解き的な総合戦 </td>
</tr>
</tbody>
</table>


<h2>日本チームの活躍</h2>

<p>秋葉拓哉氏らの Team Unagi が通算7回優勝している常勝チーム（2013・2015・2019・2024・2025年など）。2019年・2024年はRustを使用して優勝しており、"Rust is the programming language of choice for discriminating hackers" が宣言された。2025年は Sakana AI の進化的コード生成ツール ShinkaEvolve を人間の競技者と組み合わせて優勝したことが話題になった。</p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/ICFP_Programming_Contest">ICFP Programming Contest - Wikipedia</a></li>
<li><a href="https://icfpconference.org/contest.html">ICFP Programming Contest (icfpconference.org)</a></li>
<li><a href="https://icfpc-unagi.github.io/">Team Unagi</a></li>
<li><a href="https://sakana.ai/icfp-2025/">ShinkaEvolve in Action — Sakana AI</a></li>
<li><a href="https://www.cs.cmu.edu/~rwh/papers/contest/icfp2006.pdf">The Cult of the Bound Variable: The 9th Annual ICFP Programming Contest (CMU)</a></li>
</ul>

]]></description>
</item>
<item>
<title>勾配降下法</title>
<link>https://64p.org/notes/gradient-descent.html</link>
<guid isPermaLink="true">https://64p.org/notes/gradient-descent.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>勾配降下法</h1>

<p><a class="note-tag" href="https://64p.org/notes/tags/math.html">#math</a> <a class="note-tag" href="https://64p.org/notes/tags/machine-learning.html">#machine-learning</a></p>

<p>微分可能な関数の（局所）最小値を反復計算で探す最適化アルゴリズム。機械学習で損失関数を最小化するパラメータを求める際の基本手法。</p>

<div class="math-display">
\theta_{t+1} = \theta_t - \eta \, \nabla f(\theta_t)
</div>


<p>勾配 <span class="math-inline">\nabla f</span> は<a href="https://64p.org/notes/derivative.html">微分</a>係数の多変数版（各変数での偏微分を並べたベクトル）で、「その点で関数が最も急に増える方向」を指す。その<strong>逆方向</strong>に少しずつ進めば関数値が下がっていく、というのが全体のアイデア。霧の中で山を下るとき、足元の傾きだけを頼りに一番急な下り方向へ一歩ずつ進むのに例えられる。</p>

<h2>学習率</h2>

<p>ステップ幅を決める係数 <span class="math-inline">\eta</span> を<strong>学習率</strong>と呼ぶ。代表的なハイパーパラメータで、トレードオフがある。</p>

<ul>
<li>小さすぎる — 収束までの反復回数が膨大になり学習が遅い</li>
<li>大きすぎる — 最小値を飛び越えて振動・発散する</li>
</ul>


<h2>バリエーション</h2>

<p>勾配を計算するときに使うデータ量で分類される。</p>

<ul>
<li><strong>バッチ勾配降下法</strong> — 全訓練データで勾配を計算。正確だが1ステップが重い</li>
<li><strong>確率的勾配降下法（SGD）</strong> — 1サンプルだけで勾配を近似。1ステップが軽く、ノイズが局所解からの脱出に効くこともある</li>
<li><strong>ミニバッチ勾配降下法</strong> — 小さなサブセットで勾配を近似する折衷案。深層学習の実務ではこれが標準</li>
</ul>


<p>学習率を自動調整する発展形として Momentum、AdaGrad、Adam などがある。</p>

<h2>機械学習との関係</h2>

<p>ニューラルネットワークの学習は「損失関数をパラメータで偏微分した勾配を誤差逆伝播法（backpropagation）で効率よく計算し、勾配降下法でパラメータを更新する」の反復。導関数が 0 になる点を解析的に解けない巨大な関数でも、勾配さえ計算できれば数値的に最小化へ向かえるのがポイント。</p>

<h2>出典</h2>

<ul>
<li><a href="https://builtin.com/data-science/gradient-descent">What Is Gradient Descent? - Built In</a></li>
<li><a href="https://www.ibm.com/think/topics/learning-rate">What is Learning Rate in Machine Learning? - IBM</a></li>
<li><a href="https://medium.com/munchy-bytes/navigating-the-learning-curve-gradient-descent-stochastic-gradient-descent-in-ml-e8ec03efa673">A Guide to Gradient Descent and Stochastic Gradient Descent - Medium</a></li>
</ul>

]]></description>
</item>
<item>
<title>微分方程式</title>
<link>https://64p.org/notes/differential-equation.html</link>
<guid isPermaLink="true">https://64p.org/notes/differential-equation.html</guid>
<pubDate>Sat, 26 Sep 2026 08:03:00 +0900</pubDate>
<description><![CDATA[<h1>微分方程式</h1>

<p><a class="note-tag" href="https://64p.org/notes/tags/math.html">#math</a></p>

<p>未知の<strong>関数</strong>とその導関数（<a href="https://64p.org/notes/derivative.html">微分</a>）の間の関係を記述した方程式。普通の方程式の解が「数」なのに対し、微分方程式の解は「関数」になる。「変化のルール（変化率）から挙動そのもの（関数）を復元する」問題であり、物理・工学でのモデル記述の基本言語。</p>

<h2>例</h2>

<ul>
<li><strong>指数増殖</strong> — <span class="math-inline">\frac{dy}{dt} = ky</span>（増加率が現在量に比例）。解は <span class="math-inline">y = Ce^{kt}</span>。人口増加・放射性崩壊・複利</li>
<li><strong>ニュートンの冷却法則</strong> — <span class="math-inline">\frac{dy}{dt} = k(A - y)</span>（温度差に比例して冷める）</li>
<li><strong>減衰振動</strong> — <span class="math-inline">m\frac{d<sup>2x</sup>}{dt<sup>2</sup>} + c\frac{dx}{dt} + kx = f(t)</span>。バネ・ダンパー系や RLC 回路がこの形</li>
</ul>


<h2>分類</h2>

<ul>
<li><strong>常微分方程式（ODE）</strong> — 未知関数が1変数で、通常の導関数だけを含む。1次元の力学系のモデルに多い</li>
<li><strong>偏微分方程式（PDE）</strong> — 未知関数が多変数で、偏導関数を含む。熱・波動・流体・電磁気・量子力学など、空間的な広がりを持つ系のモデルに多い</li>
<li><strong>階数（order）</strong> — 含まれる導関数の最高階。上の冷却法則は1階、減衰振動は2階</li>
<li><strong>線形/非線形</strong> — 未知関数とその導関数について線形かどうか。線形なら解の重ね合わせが効き、理論が整っている</li>
</ul>


<h2>解き方</h2>

<ul>
<li><strong>解析的に解く</strong> — 変数分離などの求積法（<a href="https://64p.org/notes/integral.html">積分</a>に帰着させる）、<a href="https://64p.org/notes/laplace-transform.html">ラプラス変換</a>（微分を代数演算に変えて機械的に解く）、<a href="https://64p.org/notes/fourier-transform.html">フーリエ変換</a>（偏微分方程式向き）など。ただし解析解が求まるのは限られたクラスだけ</li>
<li><strong>数値的に解く</strong> — オイラー法・ルンゲクッタ法などで数値解を計算する。実務ではこちらが主流</li>
</ul>


<h2>出典</h2>

<ul>
<li><a href="https://tutorial.math.lamar.edu/classes/de/definitions.aspx">Differential Equations - Definitions - Paul&rsquo;s Online Notes (Lamar University)</a></li>
<li><a href="https://web.uvic.ca/~tbazett/diffyqs/classification_section.html">Classification of differential equations - University of Victoria</a></li>
<li><a href="https://phas.ubc.ca/~berciu/TEACHING/PHYS312/LECTURES/FILES/defs.pdf">Definitions and important facts regarding ODEs and PDEs - UBC</a></li>
</ul>

]]></description>
</item>
<item>
<title>Kubernetes Operator（Operatorパターン）</title>
<link>https://64p.org/notes/kubernetes-operator.html</link>
<guid isPermaLink="true">https://64p.org/notes/kubernetes-operator.html</guid>
<pubDate>Sat, 26 Sep 2026 08:01:00 +0900</pubDate>
<description><![CDATA[<h1>Kubernetes Operator（Operatorパターン）</h1>

<p><a href="https://64p.org/notes/kubernetes-custom-resource.html">カスタムリソース</a>と<a href="https://64p.org/notes/kubernetes-controller.html">コントローラ</a>を組み合わせて、特定のアプリケーション（とその構成要素）を管理するKubernetesの拡張。「人間の運用者（operator）がサービスを管理するときに持っている知識」をコードにして自動化する、というのが名前の由来。 <a class="note-tag" href="https://64p.org/notes/tags/kubernetes.html">#kubernetes</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure.html">#infrastructure</a></p>

<h2>構成要素</h2>

<ul>
<li><strong>カスタムリソース</strong> — 管理対象の設定を表す独自の型（例: <code>SampleDB</code>）</li>
<li><strong>コントローラ</strong> — そのカスタムリソースをwatchしてreconcileする。Kubernetes APIのクライアントとしてPodで動く</li>
<li>Kubernetes本体のコードは一切変更しない。</li>
</ul>


<p>公式ドキュメントのSampleDBの例では、Operatorが次をやる:</p>

<ul>
<li>ストレージ用のPersistentVolumeClaimを作る</li>
<li>DBインスタンスをStatefulSetで動かす</li>
<li>初期設定をJobで流す</li>
<li>定期的にバックアップ用のPodを動かす</li>
<li>DBのバージョンアップを自動で行う</li>
</ul>


<p>ユーザー側はこれだけ:</p>

<pre><code class="sh">kubectl get SampleDB                   # 設定済みのDB一覧
kubectl edit SampleDB/example-database # 設定を変える
</code></pre>

<h2>Operatorで自動化されがちなこと</h2>

<ul>
<li>アプリケーションのデプロイ</li>
<li>バックアップの取得・リストア</li>
<li>スキーマ移行を伴うアップグレード</li>
<li>Kubernetes外のAPIをServiceとして公開する</li>
<li>障害のシミュレーション（耐障害性テスト）</li>
<li>分散アプリケーションのリーダー選出</li>
</ul>


<h2>実装フレームワーク</h2>

<ul>
<li>kubebuilder（Go）</li>
<li>Operator Framework（Operator SDK）</li>
<li>Kopf（Python）</li>
<li>Java Operator SDK</li>
<li>KubeOps（.NET）</li>
<li>kube-rs（Rust）</li>
<li>Metacontroller（webhookベース）</li>
</ul>


<h2>歴史</h2>

<p>2016年にCoreOSが提唱した。</p>

<h2>「コントローラ」と「Operator」の違い</h2>

<ul>
<li>コントローラ: 制御ループ一般。Deployment/Jobなどの組み込みのものも含む。</li>
<li>Operator: カスタムリソース + それ専用のコントローラで、特定アプリの運用知識を詰め込んだもの。いわば「コントローラの使い方の一パターン」。</li>
<li>厳密な線引きがあるわけではなく、カスタムリソース用のコントローラなら何でもOperatorと呼ばれることも多い（ピザを注文するコントローラなど、<a href="https://64p.org/notes/kubernetes-custom-resource.html">Kubernetesのカスタムリソース（CRD）</a>参照）。</li>
</ul>


<h2><a href="https://64p.org/notes/kubernetes-extension-terms.html">Kubernetes拡張まわりの用語整理</a>の中での位置づけ</h2>

<p>CRDとコントローラの組み合わせ方の一パターン。用語としては一番上位（CRD・CR・コントローラをすべて含む）。</p>

<h2>出典</h2>

<ul>
<li><a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/">Operator pattern | Kubernetes</a></li>
<li><a href="https://web.archive.org/web/20170129131616/https://coreos.com/blog/introducing-operators.html">Introducing Operators - CoreOS (archive)</a></li>
</ul>

]]></description>
</item>
<item>
<title>Kubernetes拡張まわりの用語整理</title>
<link>https://64p.org/notes/kubernetes-extension-terms.html</link>
<guid isPermaLink="true">https://64p.org/notes/kubernetes-extension-terms.html</guid>
<pubDate>Sat, 26 Sep 2026 08:01:00 +0900</pubDate>
<description><![CDATA[<h1>Kubernetes拡張まわりの用語整理</h1>

<p>CRD・CR・コントローラ・Operator・reconcileあたりの用語が混ざりやすいので、関係を一枚にまとめるハブノート。深掘りは各ノートで。 <a class="note-tag" href="https://64p.org/notes/tags/kubernetes.html">#kubernetes</a> <a class="note-tag" href="https://64p.org/notes/tags/moc.html">#moc</a></p>

<div class="mermaid">
flowchart LR
  CRD["CRD&lt;br/&gt;(型の定義)"] --&gt;|型を追加| API["kube-apiserver&lt;br/&gt;(etcdに保存)"]
  User["ユーザー&lt;br/&gt;kubectl apply"] --&gt;|CRを作る&lt;br/&gt;spec=望ましい状態| API
  Ctrl["コントローラ&lt;br/&gt;(制御ループ)"] --&gt;|watch| API
  Ctrl --&gt;|reconcile&lt;br/&gt;差分を埋める| World["現実&lt;br/&gt;Pod / クラウド / 外部API"]
  Ctrl --&gt;|statusを書き戻す| API
</div>


<h2>用語</h2>

<table>
<thead>
<tr>
<th> 用語 </th>
<th> 一言で </th>
<th> プログラミングでいうと </th>
</tr>
</thead>
<tbody>
<tr>
<td> リソース / Kind </td>
<td> APIが扱うものの種類（Pod, Deployment, …） </td>
<td> 型・クラス </td>
</tr>
<tr>
<td> オブジェクト </td>
<td> その種類の個々の実体（<code>my-pod</code>など） </td>
<td> インスタンス </td>
</tr>
<tr>
<td> <code>spec</code> </td>
<td> ユーザーが書く「望ましい状態」 </td>
<td> 入力 </td>
</tr>
<tr>
<td> <code>status</code> </td>
<td> コントローラが書く「実際の状態」 </td>
<td> 出力 </td>
</tr>
<tr>
<td> [[kubernetes-custom-resource|CRD]] </td>
<td> 独自の型を追加する定義 </td>
<td> クラス定義を追加 </td>
</tr>
<tr>
<td> CR（カスタムリソース） </td>
<td> CRDで作った個々のオブジェクト </td>
<td> 独自クラスのインスタンス </td>
</tr>
<tr>
<td> [[kubernetes-controller|コントローラ]] </td>
<td> watchして差分を埋め続けるループ </td>
<td> 常駐プロセス </td>
</tr>
<tr>
<td> reconcile </td>
<td> 差分を埋める1回分の処理 </td>
<td> ループの1イテレーション </td>
</tr>
<tr>
<td> [[kubernetes-operator|Operator]] </td>
<td> CRD + 専用コントローラで特定アプリの運用を自動化したもの </td>
<td> ライブラリ化された運用手順 </td>
</tr>
</tbody>
</table>


<h2>関係の要点</h2>

<ul>
<li>CRDだけでは何も起きない（データが保存されるだけ）。動かすのはコントローラ。</li>
<li>組み込みリソース（Deploymentなど）も、組み込みのコントローラが動かしているだけで、構造はCRと同じ。</li>
<li>「CRD + コントローラ」で特定アプリを管理するものがOperator。</li>
<li>この仕組みをクラスタ自体に当てはめたのが<a href="https://64p.org/notes/cluster-api.html">Cluster API</a>、クラウド連携部分を切り出したのが<a href="https://64p.org/notes/kubernetes-cloud-controller-manager.html">Cloud Controller Manager</a>。</li>
</ul>


<p>親ハブ: <a href="https://64p.org/notes/kubernetes.html">Kubernetes</a></p>
]]></description>
</item>
<item>
<title>Kubernetesのコントローラ（制御ループ・reconcile）</title>
<link>https://64p.org/notes/kubernetes-controller.html</link>
<guid isPermaLink="true">https://64p.org/notes/kubernetes-controller.html</guid>
<pubDate>Sat, 26 Sep 2026 08:01:00 +0900</pubDate>
<description><![CDATA[<h1>Kubernetesのコントローラ（制御ループ・reconcile）</h1>

<p>クラスタの状態をwatchし、「実際の状態（current state）」を「望ましい状態（desired state）」に近づける変更を行い続けるループ。<a href="https://64p.org/notes/kubernetes.html">Kubernetes</a>の動作はほぼ全部これの組み合わせでできている。 <a class="note-tag" href="https://64p.org/notes/tags/kubernetes.html">#kubernetes</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure.html">#infrastructure</a></p>

<h2>公式ドキュメントのたとえ: サーモスタット</h2>

<ul>
<li>設定温度 = 望ましい状態</li>
<li>室温 = 実際の状態</li>
<li>サーモスタットが暖房をON/OFFして室温を設定温度に近づける = コントローラの動作</li>
</ul>


<p>この「差分を見て埋める」1回分の処理を <strong>reconcile</strong>（突き合わせ）と呼び、それを繰り返すのが <strong>制御ループ（control loop）</strong> / reconcileループ。</p>

<h2>spec と status</h2>

<ul>
<li>コントローラは最低1種類のリソースを追跡し、その <code>spec</code> フィールドを望ましい状態として読む。</li>
<li>実際にやったことの結果は <code>status</code> に書き戻す。</li>
<li>ユーザーは <code>spec</code> を書くだけ、<code>status</code> はコントローラが書く、という役割分担。</li>
</ul>


<h2>例: Jobコントローラ</h2>

<ul>
<li>新しい <code>Job</code> オブジェクトをwatchする（望ましい状態）</li>
<li>仕事を実行する <code>Pod</code> を作る（コンテナを自分で動かすわけではなく、API server経由で他のコンポーネントに任せる）</li>
<li>終わったら <code>Job</code> の <code>status</code> を更新する</li>
</ul>


<p>「あるリソースを望ましい状態として読み、別のリソースを作って実現する」という分離が基本形。DeploymentコントローラもJobコントローラもPodを作るが、ラベルで自分の管理対象を区別しているので干渉しない。</p>

<h2>2つの制御方式</h2>

<ol>
<li><strong>API server経由</strong>（大半）— JobコントローラのようにKubernetesのオブジェクトを作って間接的に実現する。</li>
<li><strong>外部を直接操作</strong> — クラスタ外のシステムを直接叩く。ノードを増やすオートスケーラーや、<a href="https://64p.org/notes/kubernetes-cloud-controller-manager.html">Cloud Controller Manager</a>のようにクラウドのAPIを叩くもの。</li>
</ol>


<h2>どこで動いているか</h2>

<ul>
<li>Deployment / Job / ReplicaSet などの組み込みコントローラは <strong>kube-controller-manager</strong> の中でまとめて動く。</li>
<li>クラウド連携系は<a href="https://64p.org/notes/kubernetes-cloud-controller-manager.html">cloud-controller-manager</a>に分離されている。</li>
<li>自作のコントローラは普通のPodとしてクラスタ内で動かす。<a href="https://64p.org/notes/kubernetes-custom-resource.html">カスタムリソース</a>と組み合わせたものが<a href="https://64p.org/notes/kubernetes-operator.html">Operator</a>。</li>
</ul>


<h2>設計上のポイント</h2>

<ul>
<li>巨大な1つのループではなく、それぞれが1つの側面を担当する小さなコントローラを多数動かす。</li>
<li>クラスタは常に変化しているので、完全に安定した状態に到達しないこともある。コントローラが動いて有用な変更を続けていればそれでよい、という考え方。</li>
<li>同じパターンをクラスタそのものに適用したのが<a href="https://64p.org/notes/cluster-api.html">Cluster API</a>。</li>
</ul>


<h2><a href="https://64p.org/notes/kubernetes-extension-terms.html">Kubernetes拡張まわりの用語整理</a>の中での位置づけ</h2>

<p>Kubernetesを動かす仕組みの中核。CRDは「型」、コントローラは「それを動かす処理」、Operatorは「その組み合わせ方の一パターン」という関係。</p>

<h2>出典</h2>

<ul>
<li><a href="https://kubernetes.io/docs/concepts/architecture/controller/">Controllers | Kubernetes</a></li>
</ul>

]]></description>
</item>
<item>
<title>Kubernetesのカスタムリソース（CRD）</title>
<link>https://64p.org/notes/kubernetes-custom-resource.html</link>
<guid isPermaLink="true">https://64p.org/notes/kubernetes-custom-resource.html</guid>
<pubDate>Sat, 26 Sep 2026 07:54:00 +0900</pubDate>
<description><![CDATA[<h1>Kubernetesのカスタムリソース（CRD）</h1>

<p>CustomResourceDefinition (CRD) を登録すると、<a href="https://64p.org/notes/kubernetes.html">Kubernetes</a> APIに独自の型（Kind）を追加できる。登録した瞬間から <code>kubectl get/apply/delete</code> やwatchが組み込みリソースと同じように使える。実体は「スキーマ付きのJSONを<a href="https://64p.org/notes/etcd.html">etcd</a>に保存し、REST APIで出し入れする仕組み」。 <a class="note-tag" href="https://64p.org/notes/tags/kubernetes.html">#kubernetes</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure.html">#infrastructure</a></p>

<h2>CRDとコントローラは別物</h2>

<p>用語の関係は<a href="https://64p.org/notes/kubernetes-extension-terms.html">Kubernetes拡張まわりの用語整理</a>に整理。</p>

<ul>
<li>CRD単体はただのデータ置き場。オブジェクトを作っても何も起きない。</li>
<li>現実に何かを起こすのは<a href="https://64p.org/notes/kubernetes-controller.html">コントローラ</a>（<a href="https://64p.org/notes/kubernetes-operator.html">Operator</a>）で、CRを watch して「望ましい状態（spec）」に「実際の状態」を近づけるreconcileループを回し、結果を <code>status</code> に書き戻す。</li>
<li>なので「何でも登録できるか」の答えは、データとしてはJSONで書けるものなら大体何でも可。何を起こせるかはコントローラ次第で、クラスタ外の物理世界でも構わない（後述のピザ）。</li>
</ul>


<h2>カスタムリソースで管理するメリット</h2>

<h3>Kubernetes APIの機能がタダで付いてくる</h3>

<p>CRDを登録するだけで組み込みリソースと同じ機能が使える。認証・認可・永続化・CLIを自作しなくてよい。</p>

<table>
<thead>
<tr>
<th> 機能 </th>
<th> うれしさ </th>
</tr>
</thead>
<tbody>
<tr>
<td> CRUD・watch </td>
<td> 変更検知の仕組みを書かなくていい </td>
</tr>
<tr>
<td> kubectl対応 </td>
<td> <code>get</code>/<code>describe</code>/<code>edit</code>/<code>--watch</code> がそのまま使える </td>
</tr>
<tr>
<td> RBAC </td>
<td> 「作れるが消せない」などの権限を既存の仕組みで書ける </td>
</tr>
<tr>
<td> 監査ログ </td>
<td> 誰がいつ何を変えたかが残る </td>
</tr>
<tr>
<td> バリデーション </td>
<td> スキーマ・[[common-expression-language|CEL]]・Admission Webhookで不正値をはじける </td>
</tr>
<tr>
<td> Finalizer </td>
<td> 削除前の後始末（外部リソースの削除など）をフックできる </td>
</tr>
<tr>
<td> バージョニング </td>
<td> <code>v1alpha1</code> → <code>v1</code> の移行と変換の仕組み </td>
</tr>
<tr>
<td> Discovery・JSON Patch・Dashboard </td>
<td> APIとして発見でき、部分更新でき、UIにも出る </td>
</tr>
</tbody>
</table>


<h3>宣言的に管理できる</h3>

<ul>
<li>ユーザーは <code>spec</code>（望ましい状態）を書くだけで手順は書かない。</li>
<li><a href="https://64p.org/notes/kubernetes-controller.html">コントローラ</a>がreconcileし続けるので、手で壊されても元に戻る（自己修復・ドリフト修正）。</li>
<li>結果は <code>status</code> に出るので状態確認の方法が統一される。</li>
</ul>


<h3>複雑なものを1枚のYAMLに抽象化できる</h3>

<pre><code class="yaml">apiVersion: example.com/v1
kind: Database
metadata:
  name: my-database
spec:
  engine: PostgreSQL
  version: "14"
  replicas: 3
</code></pre>

<p>これだけでStatefulSet・PVC・Service・バックアップJobなどが作られる、という形にできる。運用知識をコントローラ側に閉じ込め、利用者にはシンプルな入口だけ見せる。これが<a href="https://64p.org/notes/kubernetes-operator.html">Operator</a>の価値。</p>

<h3>既存エコシステムに乗る</h3>

<ul>
<li>Argo CD / FluxのようなGitOps、Helm、kustomizeで他のマニフェストと同じように扱える。</li>
<li>アプリもDBも証明書もクラウドリソースも、同じkubectlとYAMLで扱えるという統一感が一番大きい。</li>
</ul>


<h2>向かないケース・導入時の注意</h2>

<p>公式ドキュメントでは、宣言的APIに当てはまらないものは独立したAPIサーバーにすることを勧めている。宣言的APIの特徴は:</p>

<ul>
<li>小さなオブジェクトが比較的少数</li>
<li>アプリやインフラの設定を表す</li>
<li>更新頻度が低い</li>
<li>人間が読み書きする</li>
<li>主な操作がCRUDで、オブジェクトをまたぐトランザクションが不要</li>
</ul>


<p>逆に次のようなものは向かない:</p>

<ul>
<li>「これやって」と頼んで同期的に結果を待つRPC的な操作、IDを返して別途ステータスを聞きに行く操作</li>
<li>1オブジェクト数kB超、または数千個以上のオブジェクト（サイズ上限は後述の「制約」参照）</li>
<li>毎秒数十リクエストのような高頻度アクセス</li>
<li>エンドユーザーのデータ（画像・個人情報など）</li>
<li>CRUDで表せない操作、オブジェクトとしてモデル化しにくいもの</li>
</ul>


<h3>ConfigMapとの使い分け</h3>

<ul>
<li><strong>ConfigMap</strong> — <code>mysql.cnf</code> のような既存フォーマットの設定ファイルを丸ごと入れ、Pod内のプログラムがファイルや環境変数として読むだけの場合。設定変更時にDeploymentのローリングアップデートで反映したい場合。</li>
<li><strong>カスタムリソース</strong> — kubectlのトップレベルで扱いたい、変更をwatchして他のオブジェクトを作る自動化をしたい、<code>spec</code>/<code>status</code> の慣習に乗りたい、複数リソースをまとめて抽象化したい、ドメイン固有のバリデーションが欲しい場合。</li>
</ul>


<h3>導入時のコスト</h3>

<ul>
<li>コントローラという新しいコードがクラスタ内で動くので、それ自体の監視・トラブルシュートが必要になる。暴走するとクラスタの安定性に影響する。</li>
<li>データは<a href="https://64p.org/notes/etcd.html">etcd</a>に入るので、バックアップ・リストア計画とストレージ負荷を考える。</li>
<li>誰が作成・変更できるかのRBAC設計、spec内の機密情報の扱いを考える。</li>
</ul>


<h2>定義の例（公式ドキュメントのCronTab）</h2>

<pre><code class="yaml">apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.stable.example.com   # &lt;plural&gt;.&lt;group&gt; でなければならない
spec:
  group: stable.example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec: {type: string}
                image: {type: string}
                replicas: {type: integer}
  scope: Namespaced
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
    shortNames: [ct]
</code></pre>

<h2>制約</h2>

<ul>
<li><strong>名前</strong>: <code>metadata.name</code> は <code>&lt;plural&gt;.&lt;group&gt;</code> 形式。groupはドメイン名風（<code>stable.example.com</code>）。</li>
<li><strong>structural schema必須</strong>: <code>apiextensions.k8s.io/v1</code> ではOpenAPI v3の構造的スキーマが必須。スキーマにないフィールドは保存前にpruning（黙って削除）される。任意のJSONを入れたい部分には <code>x-kubernetes-preserve-unknown-fields: true</code> を付ける。</li>
<li><strong>バリデーション</strong>: スキーマに加え、<a href="https://64p.org/notes/common-expression-language.html">CEL</a>でフィールド間の制約をkube-apiserver内で書ける（webhook不要）。</li>
<li><strong>サイズ</strong>: etcdのリクエストサイズ上限がデフォルト1.5MiB（<code>--max-request-bytes</code>）なので、1オブジェクトはそれ以下に収める必要がある。エンコードやメタデータのオーバーヘッドもあるので、ギリギリを狙うのは危ない。大きなデータ・高頻度に書き換わるデータの置き場には向かない。</li>
<li><strong>CRDを消すと中身も消える</strong>: CRDを削除するとAPIエンドポイントが消え、そのCRDのカスタムオブジェクトも全部削除される。作り直しても空から。</li>
</ul>


<h2>変わった使い方の例: ピザを注文する</h2>

<p>「宣言 → reconcile」の形に当てはまれば、クラスタ外の現実世界の状態も扱えることを示すネタ実装がいくつかある。いずれもDomino'sのAPIを叩いて本当に注文する。</p>

<ul>
<li><strong>rudoi/cruster-api</strong> — kubebuilder製。<code>PizzaOrder</code> リソースを作るとコントローラが実際に発注し、<code>kubectl get pizzaorders</code> でPREP → BAKE → QUALITY CHECK → DELIVEREDの進捗を追える。誤発注防止の <code>placeOrder</code> フラグ、支払い情報はSecret参照。米国限定・ピザのみ。作者いわく実際の注文は1回。</li>
<li><strong>cirocosta/pizza-controller</strong> — <code>PizzaCustomer</code>（住所など）/ <code>PizzaStore</code>（店舗とメニュー）/ <code>PizzaOrder</code> の3種のCRD。<code>kubectl get pizzacustomer</code> で最寄り店舗、<code>kubectl get pizzastore store-123 -o yaml</code> でメニューが見られる。</li>
</ul>


<pre><code class="yaml">kind: PizzaOrder
apiVersion: ops.tips/v1
metadata:
  name: ma-pizza
spec:
  yeahSurePlaceThisOrder: true
  storeRef: {name: store-123}
  customerRef: {name: you}
  payment:
    creditCardSecretRef: {name: cc}
  items:
    - ticker: 10SCREEN
      quantity: 1
</code></pre>

<ul>
<li><strong>Crossplaneのprovider</strong> — Crossplane公式ブログで、Provider作りの題材としてDomino&rsquo;s APIのproviderを作ってピザを注文している。Crossplaneがクラウドリソースを扱うのと全く同じ構造。</li>
</ul>


<p>ほかにMinecraftサーバーを <code>MinecraftServer</code> リソースとして宣言するOperatorなどもある（こちらはPodを立てるので比較的まっとう）。</p>

<h2>考えたこと</h2>

<ul>
<li>ピザの例が面白いのは、reconcileモデルの汎用性を端的に示している点。「外部APIの向こうにある状態」を宣言的に管理するという意味では、<a href="https://64p.org/notes/cluster-api.html">Cluster API</a>がクラスタそのものをリソース化しているのと同じ発想。</li>
<li>逆に言うと、CRDは「kubectlで扱えるスキーマ付きKVS」としても使えてしまうが、etcdのサイズ上限や書き込み負荷を考えると、汎用DB代わりにするものではない。</li>
<li>CRDやOperatorを試すなら<a href="https://64p.org/notes/kind.html">kind (Kubernetes in Docker)</a>で使い捨てクラスタを立てるのが手軽。</li>
</ul>


<h2><a href="https://64p.org/notes/kubernetes-extension-terms.html">Kubernetes拡張まわりの用語整理</a>の中での位置づけ</h2>

<p>「型を追加する」部分だけを担う。単体ではデータ置き場で、動作はコントローラが担う。</p>

<h2>出典</h2>

<ul>
<li><a href="https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/">Extend the Kubernetes API with CustomResourceDefinitions | Kubernetes</a></li>
<li><a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">Custom Resources | Kubernetes</a></li>
<li><a href="https://kubernetes.io/blog/2019/06/20/crd-structural-schema/">Future of CRDs: Structural Schemas | Kubernetes</a></li>
<li><a href="https://etcd.io/docs/v3.3/dev-guide/limit/">System limits | etcd</a></li>
<li><a href="https://github.com/rudoi/cruster-api">rudoi/cruster-api - GitHub</a></li>
<li><a href="https://github.com/cirocosta/pizza-controller">cirocosta/pizza-controller - GitHub</a></li>
<li><a href="https://ops.tips/notes/kubernetes-pizza/">kubectl create pizza | ops.tips</a></li>
<li><a href="https://blog.crossplane.io/providers-101-ordering-pizza-with-kubernetes-and-crossplane/">Providers 101: Ordering Pizza with Kubernetes and Crossplane</a></li>
<li><a href="https://github.com/JamesLaverack/kubernetes-minecraft-operator">JamesLaverack/kubernetes-minecraft-operator - GitHub</a></li>
</ul>

]]></description>
</item>
<item>
<title>Semaphore UI（Ansible/Terraform向けWeb UI）</title>
<link>https://64p.org/notes/semaphore-ui.html</link>
<guid isPermaLink="true">https://64p.org/notes/semaphore-ui.html</guid>
<pubDate>Sat, 26 Sep 2026 05:57:00 +0900</pubDate>
<description><![CDATA[<h1>Semaphore UI（Ansible/Terraform向けWeb UI）</h1>

<p><a href="https://64p.org/notes/ansible.html">Ansible</a>のPlaybookや<a href="https://64p.org/notes/terraform.html">Terraform</a>/<a href="https://64p.org/notes/opentofu.html">OpenTofu</a>、シェルスクリプトなどを、Webブラウザからボタン一つで実行できるようにするセルフホスト型のWeb UI + API。Go製（フロントはJavaScript）、MITライセンス。旧名は <strong>Ansible Semaphore</strong> で、当初はAnsible専用のUIだったが対応ツールが増えたため「Semaphore UI」に改名された。並行制御の<a href="https://64p.org/notes/semaphore.html">セマフォ</a>とは無関係。</p>

<ul>
<li>リポジトリ: <code>semaphoreui/semaphore</code>（2026年9月時点でstar数1.4万程度）</li>
<li>対応ツール: Ansible, Terraform, OpenTofu, Terragrunt, Bash, PowerShell, Python</li>
<li>DB: SQLite / MySQL / PostgreSQL。以前使えたBoltDBは非推奨で、2.17でSQL系DBへの移行ツールが入った</li>
<li>インストール: Docker, バイナリ, deb/rpm, Snap, 各クラウドのマーケットプレイスVM</li>
<li>最新安定版は2.19系（2.19.12, 2026-08-30）</li>
</ul>


<h2>実行モデル</h2>

<p>基本は「gitリポジトリをcloneして、その中のPlaybook/スクリプトをSemaphoreのホスト（またはrunner）上で実行し、ログをWebに流す」だけ。<a href="https://64p.org/notes/ansible.html">Ansible</a>自体がagentlessなので、Semaphoreも対象ノードに何も入れない。コントロールノードをWeb化したもの、と捉えるとわかりやすい。</p>

<h2>構成要素</h2>

<p>プロジェクト単位で以下のリソースを持つ。</p>

<ul>
<li><strong>Project</strong> — 以下のリソースをまとめる単位。チームメンバーと権限もプロジェクトごと。</li>
<li><strong>Repository</strong> — Playbook/スクリプトが入ったgitリポジトリ（GitHub, Bitbucketなど）。</li>
<li><strong>Key Store</strong> — SSH鍵、ログインパスワード、Ansible Vaultパスワードなどを暗号化して保存する。2.17からはファイルや環境変数からの読み込み（Kubernetesのsecret注入、<a href="https://64p.org/notes/vault.html">HashiCorp Vault</a> Agent連携）やDevolutions Serverもバックエンドに使える。</li>
<li><strong>Inventory</strong> — Ansible向けの対象ホスト一覧。Terraformの場合はworkspaceに相当するものを選ぶ。</li>
<li><strong>Variable Groups</strong>（旧Environment） — 変数・シークレットの組。テンプレートに複数組み合わせて注入できる。</li>
<li><strong>Task Template</strong> — 「どのリポジトリのどのファイルを、どのinventory・変数で実行するか」の定義。ブランチ指定、CLI引数（<code>["-vvv"]</code>のようなJSON配列）、実行時にユーザーへ入力を求めるsurvey変数も設定できる。</li>
<li><strong>Task</strong> — テンプレートを実際に実行した1回分。ログと結果が残る。</li>
<li><strong>Schedule</strong> — テンプレートをcronで定期実行。2.17で一回限り（日時指定）のスケジュールも追加。</li>
</ul>


<h3>テンプレートの3種類</h3>

<table>
<thead>
<tr>
<th> 種類 </th>
<th> 役割 </th>
</tr>
</thead>
<tbody>
<tr>
<td> Task </td>
<td> 普通の実行。デフォルト </td>
</tr>
<tr>
<td> Build </td>
<td> 成果物を作り、自動インクリメントのバージョン番号を振る（開始バージョンを<code>1.0.0</code>などで指定） </td>
</tr>
<tr>
<td> Deploy </td>
<td> Buildテンプレートが作ったバージョンをデプロイする。Build成功時に自動実行（Autorun）も可 </td>
</tr>
</tbody>
</table>


<p>バージョン情報などは<code>semaphore_vars</code>経由でPlaybookに渡る。単なる「Playbook実行ボタン」ではなく、簡易的なビルド→デプロイのパイプラインも組めるようになっている。</p>

<h2>Runner</h2>

<p>タスクをSemaphore本体とは別のサーバで実行させる仕組み。</p>

<ul>
<li><code>semaphore runner register</code>でサーバ発行の登録トークンを使って登録し、以後は<code>X-Runner-Token</code>で認証する。</li>
<li><strong>runner側からのポーリング</strong>（デフォルト1秒間隔、<code>check_interval_seconds</code>で調整）で仕事を取りに行く。サーバからrunnerへ接続しに行く方式ではないので、runnerを閉じたネットワークに置きやすい。</li>
<li>runnerがリポジトリをcloneしてAnsible/Terraform等を実行し、結果をサーバへ返す。</li>
<li>プロジェクト単位のrunner（Project Runners）やrunnerのタグ指定はPro機能。</li>
</ul>


<h2>エディション</h2>

<ul>
<li><strong>Community</strong> — OSS版（GitHubのもの）。</li>
<li><strong>Pro / Enterprise</strong> — 有償（Proは月20ドル〜）。Workflows（タスクの連結）、プロジェクトrunner、runnerタグ、カスタムロールによるRBAC拡張、Redisを使ったactive-active HA（Enterprise）などが入る。</li>
</ul>


<h2>AWXとの比較</h2>

<p>同じ「AnsibleにWeb UIを被せる」系のOSSとして<a href="https://64p.org/notes/ansible.html">AWX</a>（Ansible Automation Platformのupstream）がある。AWXはKubernetes上に<a href="https://64p.org/notes/kubernetes-operator.html">Operator</a>で載せる前提の大掛かりな構成なのに対し、Semaphoreは単一のGoバイナリ（+ DB、SQLiteなら外部DBすら不要）で動く。小規模チームで「Playbookを誰でも安全に叩けるようにしたい」「定期実行したい」程度ならSemaphoreの方が導入コストが低い。一方でAnsible専用ではなくTerraform等も同列に扱う点は方向性の違い。（AWXのデプロイ方式は一般的な知識によるもので、このノート作成時に裏取りはしていない）</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/ansible.html">#ansible</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure-as-code.html">#infrastructure-as-code</a> <a class="note-tag" href="https://64p.org/notes/tags/go.html">#go</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://github.com/semaphoreui/semaphore">semaphoreui/semaphore - GitHub</a></li>
<li><a href="https://semaphoreui.com/docs/">Semaphore UI Documentation</a></li>
<li><a href="https://semaphoreui.com/docs/user-guide/task-templates">Task templates | Semaphore UI</a></li>
<li><a href="https://semaphoreui.com/docs/admin-guide/runners">Runners | Semaphore UI</a></li>
<li><a href="https://semaphoreui.com/docs/user-guide/projects/runners">Project runners (Pro) | Semaphore UI</a></li>
<li><a href="https://semaphoreui.com/releases/semaphore-v2_17">Semaphore 2.17 リリースノート</a></li>
<li><a href="https://en.wikipedia.org/wiki/Semaphore_(software">Semaphore (software) - Wikipedia</a>)</li>
</ul>

]]></description>
</item>
<item>
<title>Slurm</title>
<link>https://64p.org/notes/slurm.html</link>
<guid isPermaLink="true">https://64p.org/notes/slurm.html</guid>
<pubDate>Sat, 26 Sep 2026 05:40:00 +0900</pubDate>
<description><![CDATA[<h1>Slurm</h1>

<p>HPCクラスタ向けのオープンソースのジョブスケジューラ／リソースマネージャ。公式の説明は &ldquo;an open source, fault-tolerant, and highly scalable cluster management and job scheduling system for large and small Linux clusters"。スパコンやGPUクラスタで「ログインノードにsshして<code>sbatch</code>でジョブを投げる」あの世界の標準。</p>

<h2>役割</h2>

<p>公式overviewによると主な機能は3つ。</p>

<ol>
<li>ユーザーに計算資源（ノード）を一定時間、排他的/非排他的に割り当てる</li>
<li>割り当てたノード上で並列ジョブ（典型的にはMPI）を起動・監視する枠組みを提供する</li>
<li>資源の取り合いをキュー（待ち行列）で調停する</li>
</ol>


<h2>歴史</h2>

<ul>
<li>2002年、Lawrence Livermore National Laboratory (LLNL) 中心に最初のリリース。元は &ldquo;Simple Linux Utility for Resource Management&rdquo; の略で、プロプライエタリなQuadrics RMSに触発されたもの。今は「Slurm Workload Manager」と呼ばれ、略語扱いではない。</li>
<li>2010年、元の開発者たちがSchedMDを設立し、以後SchedMDが本家ソースをメンテ。</li>
<li>ライセンスはGPLv2。C言語で書かれ、約100個のオプショナルなプラグインを持つモジュラー設計。</li>
<li>2021年11月時点でTOP500の約60%のシステムで使われている（Wikipedia）。</li>
<li>2025年12月15日、NVIDIAがSchedMDを買収したと発表。NVIDIAはSlurmをオープンソース・ベンダーニュートラルなソフトウェアとして開発・配布し続けるとしている。発表時点でTOP500のトップ10・トップ100のそれぞれ半数超で使われているとのこと。</li>
</ul>


<h2>アーキテクチャ</h2>

<div class="mermaid">
flowchart LR
  user[ユーザー&lt;br/&gt;sbatch/srun/squeue] --&gt; ctld[slurmctld&lt;br/&gt;中央マネージャ]
  ctld --&gt; d1[slurmd&lt;br/&gt;計算ノード1]
  ctld --&gt; d2[slurmd&lt;br/&gt;計算ノード2]
  ctld --&gt; d3[slurmd&lt;br/&gt;計算ノードN]
  ctld --&gt; dbd[slurmdbd&lt;br/&gt;アカウンティングDB]
  rest[slurmrestd&lt;br/&gt;REST API] --&gt; ctld
</div>


<ul>
<li><strong>slurmctld</strong> — 中央のマネージャ。資源とジョブを監視・スケジュールする。バックアップを置ける。</li>
<li><strong>slurmd</strong> — 各計算ノードで動くデーモン。ジョブを実行し状態を報告する。</li>
<li><strong>slurmdbd</strong> — オプション。複数クラスタのアカウンティング情報をDBに記録する（<code>sacct</code>や fair share の元データ）。</li>
<li><strong>slurmrestd</strong> — オプション。REST APIでSlurmを操作するためのデーモン。</li>
</ul>


<h2>概念</h2>

<ul>
<li><strong>node</strong> — 計算資源の単位</li>
<li><strong>partition</strong> — ノードの論理グループ。実質ジョブキュー（例: <code>gpu</code>, <code>debug</code>, <code>long</code>）。パーティションごとに最大実行時間やアクセス権を設定する</li>
<li><strong>job</strong> — ユーザーに一定時間割り当てられた資源</li>
<li><strong>job step</strong> — ジョブ内で起動される並列タスクの集合（ジョブの中で<code>srun</code>するたびに1ステップ）</li>
</ul>


<p>GPUなどは <strong>GRES (generic resources)</strong> として扱い、<code>--gres=gpu:2</code>や<code>--gpus=8</code>で要求する。</p>

<h2>主なコマンド</h2>

<table>
<thead>
<tr>
<th> コマンド </th>
<th> 役割 </th>
</tr>
</thead>
<tbody>
<tr>
<td> <code>sbatch</code> </td>
<td> バッチスクリプトを投入 </td>
</tr>
<tr>
<td> <code>srun</code> </td>
<td> ジョブ/ジョブステップを起動（対話的にも使う） </td>
</tr>
<tr>
<td> <code>salloc</code> </td>
<td> 資源だけ確保してシェルを得る </td>
</tr>
<tr>
<td> <code>squeue</code> </td>
<td> キュー中のジョブの状態 </td>
</tr>
<tr>
<td> <code>sinfo</code> </td>
<td> ノード・パーティションの状態 </td>
</tr>
<tr>
<td> <code>scancel</code> </td>
<td> ジョブのキャンセル </td>
</tr>
<tr>
<td> <code>sacct</code> </td>
<td> 終了したジョブを含む実行履歴（アカウンティング） </td>
</tr>
<tr>
<td> <code>scontrol</code> </td>
<td> 管理用。ジョブやノードの詳細表示・変更 </td>
</tr>
</tbody>
</table>


<h2>バッチスクリプトの例</h2>

<p><code>#SBATCH</code>コメントでオプションを書き、<code>sbatch job.sh</code>で投げる。</p>

<pre><code class="sh">#!/bin/bash
#SBATCH --job-name=train
#SBATCH --partition=gpu
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=8
#SBATCH --gres=gpu:8
#SBATCH --time=1-00:00:00      # days-hours:minutes:seconds
#SBATCH --output=logs/%j.out   # %j = ジョブID

srun python train.py
</code></pre>

<ul>
<li><code>--array=0-99%10</code> — ジョブ配列。100個のタスクを同時最大10個で流す。各タスクでは<code>$SLURM_ARRAY_TASK_ID</code>が添字、出力名は<code>%A_%a</code>（配列ジョブID_添字）が使える。パラメータスイープの定番。</li>
<li><code>--dependency=afterok:&lt;jobid&gt;</code> — 指定ジョブが成功したら開始。前処理→学習→評価のようなパイプラインを組める。</li>
</ul>


<h2>Kubernetesとの違い（感覚的なメモ）</h2>

<p><a href="https://64p.org/notes/kubernetes.html">Kubernetes</a>（やその祖先の<a href="https://64p.org/notes/google-borg.html">Borg</a>）が「常駐するサービスを望ましい状態に保つ」ことを主眼にしているのに対し、Slurmは「有限時間で終わるバッチジョブに、ノードをまとめて（MPIならギャングで）割り当てる」ことに特化している。<code>--time</code>で実行時間の上限を申告させるのも、それを使ってバックフィル（大きいジョブの待ち時間の隙間に短いジョブを詰める）をするためである。※この節は公式資料の対比ではなく自分の整理。</p>

<h2>関連</h2>

<ul>
<li>HPCクラスタでは、Slurmで割り当てたノード群から共有の並列ファイルシステム（<a href="https://64p.org/notes/lustre.html">Lustre</a>など）を<code>/scratch</code>的にマウントして読み書きするのが典型構成。</li>
</ul>


<h2>出典</h2>

<ul>
<li><a href="https://slurm.schedmd.com/overview.html">Slurm Workload Manager - Overview</a></li>
<li><a href="https://slurm.schedmd.com/sbatch.html">Slurm Workload Manager - sbatch</a></li>
<li><a href="https://en.wikipedia.org/wiki/Slurm_Workload_Manager">Slurm Workload Manager - Wikipedia</a></li>
<li><a href="https://blogs.nvidia.com/blog/nvidia-acquires-schedmd">NVIDIA Acquires Open-Source Workload Management Provider SchedMD | NVIDIA Blog</a></li>
<li><a href="https://www.hpcwire.com/2026/01/06/what-does-nvidias-acquisition-of-schedmd-mean-for-slurm/">What Does Nvidia&rsquo;s Acquisition of SchedMD Mean for Slurm? - HPCwire</a></li>
</ul>


<p><a class="note-tag" href="https://64p.org/notes/tags/hpc.html">#hpc</a> <a class="note-tag" href="https://64p.org/notes/tags/scheduler.html">#scheduler</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure.html">#infrastructure</a></p>
]]></description>
</item>
<item>
<title>Lustre</title>
<link>https://64p.org/notes/lustre.html</link>
<guid isPermaLink="true">https://64p.org/notes/lustre.html</guid>
<pubDate>Sat, 26 Sep 2026 05:40:00 +0900</pubDate>
<description><![CDATA[<h1>Lustre</h1>

<p>HPC向けのオープンソース並列分散ファイルシステム。名前は Linux + cluster のかばん語。大量の計算ノードから1つのPOSIXファイルシステムとして見え、データを多数のストレージサーバーに分散（ストライピング）して集約帯域を稼ぐ。<a href="https://64p.org/notes/slurm.html">Slurm</a>で動くスパコンの<code>/scratch</code>や<code>/work</code>の裏にいることが多い。</p>

<h2>歴史</h2>

<ul>
<li>1999年、Peter J. Braam がカーネギーメロン大学で研究プロジェクトとして設計を開始。</li>
<li>2001年、Braam が Cluster File Systems, Inc. を設立。</li>
<li>2007年9月、Sun Microsystems が Cluster File Systems の資産を取得。</li>
<li>2010年12月、Sunを買収したOracleが Lustre 2.x の開発を止めると発表。これを受けてコミュニティ側で開発を続ける動きが出て、Whamcloud などが立ち上がる。</li>
<li>2012年7月、Intel が Whamcloud を買収。</li>
<li>2018年6月、DDN (DataDirect Networks) が Intel から Lustre チームを取得し、Whamcloud を独立部門として復活。</li>
<li>ライセンスは GPLv2 / LGPL。</li>
<li>2005年6月以降、TOP500のトップ10の少なくとも半数、トップ100の60以上で使われている（Wikipedia）。Frontier（2022年11月の1位）もLustre。</li>
</ul>


<h2>アーキテクチャ</h2>

<p>メタデータとデータの経路が分かれているのが肝。</p>

<div class="mermaid">
flowchart LR
  c[Client&lt;br/&gt;計算ノード] -- open/stat/mkdir --&gt; mds[MDS]
  mds --- mdt[(MDT&lt;br/&gt;メタデータ)]
  c -- read/write 直接 --&gt; oss1[OSS 1]
  c -- read/write 直接 --&gt; oss2[OSS 2]
  oss1 --- ost1[(OST)]
  oss1 --- ost2[(OST)]
  oss2 --- ost3[(OST)]
  oss2 --- ost4[(OST)]
  mgs[MGS] --- mgt[(MGT&lt;br/&gt;設定)]
</div>


<ul>
<li><strong>MGS / MGT</strong> — Management Server。クラスタ内のLustreファイルシステム全部の設定を保持する。MDSとHAペアで同居させることもある。</li>
<li><strong>MDS / MDT</strong> — Metadata Server / Metadata Target。ディレクトリ階層・ファイル属性・どのOSTにデータがあるか（レイアウト）を持つ。</li>
<li><strong>OSS / OST</strong> — Object Storage Server / Object Storage Target。ファイルの中身をオブジェクトとして持つ。1ファイルシステムで数百OSS・数千OSTまでスケールし、1台のOSSは通常2〜8個のOSTを担当する。</li>
<li><strong>Client</strong> — POSIXインターフェースを提供。MDSでファイルをopenしてレイアウトを得たら、あとはOSSと直接I/Oする。POSIXテストスイートがローカルext4と同様に通るとのこと。</li>
<li><strong>LNet</strong> — Lustre専用のネットワーク層。Ethernet、InfiniBand、Omni-Path、Crayのファブリックなどに対応し、RDMAも使える。</li>
</ul>


<p>バックエンドのディスクフォーマットは <strong>ldiskfs</strong>（ext4ベース）か <strong>ZFS</strong>。上限値もこれで変わる（最大ファイルサイズ ldiskfs 31.25PB / ZFS 512PB、最大ファイルシステムサイズ 512PB / 8EB、MDTあたりのファイル数 40億 / 256兆）。</p>

<h2>ストライピング</h2>

<p>ファイルを1MB以上のチャンクに切り、複数OSTのオブジェクトにラウンドロビンで配置する（RAID 0と同じ考え方）。デフォルトは stripe count 1（1つのOSTだけ）、stripe size 1MB。巨大ファイルを多数ノードから並列に読み書きするならstripe countを増やすと帯域が伸びる。小さいファイル大量なら1のままが無難。</p>

<pre><code class="sh">lfs setstripe -c 4 -S 4M /lustre/work/bigdir   # 以後このディレクトリに作るファイルは4 OSTに4MB単位で分散
lfs setstripe -c -1 /lustre/work/huge          # -1 = 全OSTに分散
lfs getstripe /lustre/work/bigdir/file.dat     # レイアウト確認
lfs df -h                                       # MDT/OSTごとの使用量
</code></pre>

<h2>メタデータ側のスケール・その他の機能</h2>

<ul>
<li><strong>DNE (Distributed Namespace Environment)</strong> — メタデータを複数MDSに分散。ディレクトリのサブツリーを別MDTに置ける。</li>
<li><strong>PFL (Progressive File Layout)</strong> — 2.10で導入。ファイルの領域ごとに異なるレイアウトを持てる（先頭は1ストライプ、後半は多ストライプ、のように）。ファイルサイズが事前に読めなくてもそこそこ良いレイアウトになる。</li>
<li><strong>HSM</strong> — テープなどへのアーカイブ・階層ストレージ管理。</li>
</ul>


<h2>クラウドでは</h2>

<p>AWSはマネージドLustreとして FSx for Lustre を提供していて、HPC向けと位置づけられている（<a href="https://64p.org/notes/aws-s3-files.html">S3 Files</a>のノート参照）。</p>

<h2>出典</h2>

<ul>
<li><a href="https://wiki.lustre.org/Introduction_to_Lustre">Introduction to Lustre - Lustre Wiki</a></li>
<li><a href="https://en.wikipedia.org/wiki/Lustre_(file_system">Lustre (file system) - Wikipedia</a>)</li>
<li><a href="https://doc.lustre.org/lustre_manual.xhtml">Lustre Operations Manual</a></li>
</ul>


<p><a class="note-tag" href="https://64p.org/notes/tags/hpc.html">#hpc</a> <a class="note-tag" href="https://64p.org/notes/tags/filesystem.html">#filesystem</a> <a class="note-tag" href="https://64p.org/notes/tags/storage.html">#storage</a></p>
]]></description>
</item>
<item>
<title>文芸的プログラミング (Literate Programming)</title>
<link>https://64p.org/notes/literate-programming.html</link>
<guid isPermaLink="true">https://64p.org/notes/literate-programming.html</guid>
<pubDate>Sat, 26 Sep 2026 02:07:00 +0900</pubDate>
<description><![CDATA[<h1>文芸的プログラミング (Literate Programming)</h1>

<p>Donald Knuthが1984年の論文「Literate Programming」(The Computer Journal, Vol.27 No.2, pp.97-111)で提唱したプログラミングのパラダイム。コードの中にコメントを埋め込むのではなく、<strong>人間向けの文章の中にコード片を埋め込む</strong>。プログラムを「コンピュータへの指示」ではなく「人間に向けて、何をさせたいかを説明する文章」として書く。</p>

<h2>考え方</h2>

<ul>
<li>「複雑なソフトウェアは単純な部品と部品間の単純な関係からなる。プログラマの仕事はそれらを、人間の理解にとって最適な順序で述べることだ」(Knuth)。</li>
<li>コンパイラが要求する順序ではなく、説明しやすい順序でコードを並べられる。</li>
<li>コード片には「◯◯を初期化する」のような説明的な名前のマクロを付け、マクロの中からさらに別のマクロを参照する。Knuthは「プログラムはさまざまな部品からなる web(網)として捉えるのが最もよい」と言っており、トップダウン・ボトムアップのどちらにも縛られない。</li>
<li>Knuth自身、当初はドキュメントのための仕組みと考えていたが、WEBで書いたプログラムは他の言語で書いたものより良くなった、と述べている。説明を書くことで推論を明示せざるを得なくなるため。</li>
</ul>


<h2>tangle と weave</h2>

<p>1つのソースから2つの成果物を取り出す。</p>

<ul>
<li><strong>tangle</strong> — マクロを展開し、コンパイラが要求する順序に並べ替えて、コンパイル可能なソースコードを生成する。</li>
<li><strong>weave</strong> — 組版されたドキュメント(Knuthの場合TeX)を生成する。</li>
</ul>


<p>同じファイルから両方を作るので、コードとドキュメントがずれない。</p>

<h2>ツール</h2>

<ul>
<li><strong>WEB</strong> — Knuthのオリジナル。Pascal + TeX。コンピューティング分野でまだ使われていなかった数少ない3文字の英単語、ということで命名。</li>
<li><strong>CWEB</strong> — KnuthとSilvio LevyによるC/C++版。</li>
<li><strong>noweb</strong> — 言語非依存。</li>
<li><strong>Org-mode Babel</strong> — Emacs上で多言語のコードブロックを実行・tangleできる。</li>
<li><strong>knitr / Sweave</strong> — R向け。再現可能な統計レポート用。</li>
<li><strong><a href="https://64p.org/notes/jupyter-notebook.html">Jupyter Notebook</a></strong> — コードセルとMarkdownセルを交互に並べる。2010年代、データサイエンス分野での計算ノートブックの普及によって文芸的プログラミングは再評価された。</li>
</ul>


<h2>Literate Computing への拡張</h2>

<p>IPython作者のFernando Pérezは2013年に「Literate Computing」という言葉を使い、文芸的プログラミングの一歩先として位置づけた。テキストとコードと<strong>実行結果</strong>を織り交ぜ、ナラティブを生きた計算の中に直接織り込む、という考え方。Knuthの文芸的プログラミングが「プログラムを説明する文章」なのに対し、Literate Computingは「計算とその結果を説明する文章」を主眼にしている。</p>

<p>この流れをインフラ運用に持ち込んだのが<a href="https://64p.org/notes/lc4ri.html">LC4RI</a>。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/programming.html">#programming</a> <a class="note-tag" href="https://64p.org/notes/tags/jupyter.html">#jupyter</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Literate_programming">Literate programming - Wikipedia</a></li>
<li><a href="https://en.wikipedia.org/wiki/IPython">IPython - Wikipedia</a></li>
<li><a href="https://machinelearningmastery.com/ipython-from-the-shell-to-a-book-with-a-single-tool-with-fernando-perez/">IPython from the shell to a book with a single tool with Fernando Perez - MachineLearningMastery.com</a></li>
</ul>

]]></description>
</item>
<item>
<title>Jupyter Notebook</title>
<link>https://64p.org/notes/jupyter-notebook.html</link>
<guid isPermaLink="true">https://64p.org/notes/jupyter-notebook.html</guid>
<pubDate>Sat, 26 Sep 2026 02:07:00 +0900</pubDate>
<description><![CDATA[<h1>Jupyter Notebook</h1>

<p>ブラウザ上で、コード・Markdownテキスト・数式・実行結果(グラフやリッチメディア含む)を<strong>セル</strong>として順に並べて書ける計算ノートブック。Project Jupyterが開発。<a href="https://64p.org/notes/literate-programming.html">文芸的プログラミング</a>を実行結果まで含めて拡張した「Literate Computing」の代表的な道具。</p>

<h2>歴史</h2>

<ul>
<li>2001年 — Fernando PérezがPythonの対話シェルを拡張した IPython を作る。</li>
<li>2011年 — Pérez、Brian Granger、Min Ragan-Kelley が IPython Notebook の最初のバージョンをリリース。</li>
<li>2014年 — 言語非依存の部分を IPython から切り出して Project Jupyter が発足。名前は Julia・Python・R に由来し、ガリレオが木星の衛星の観測をノートに記録したことへのオマージュでもある。</li>
<li>2017年 — ACM Software System Award を受賞。</li>
<li>2018年2月 — JupyterLab リリース。</li>
<li>2023年 — Jupyter Notebook 7 リリース。JupyterLab のコンポーネントの上に作り直され、両者でコードベースと拡張機構を共有するようになった。デバッガ、ダークモード、目次、リアルタイム共同編集などが入った。</li>
<li>GitHub上のNotebookは2015年に約20万、2018年に250万、2021年1月に約1000万。</li>
</ul>


<h2>仕組み</h2>

<ul>
<li><strong>.ipynb</strong> — JSONのファイル形式。バージョン付きスキーマで、メタデータ・フォーマットバージョン・セルの配列からなる。セルにはMarkdown、コード、出力が入る。出力もファイルに保存されるので、実行結果ごと共有・閲覧できる。</li>
<li><strong>カーネル</strong> — フロントエンドとコード実行環境を分離したアーキテクチャ。プロセス間通信にZeroMQを使うプロトコルで、Python(IPythonカーネル)以外にもJulia、R、Haskell、Rubyなど数十言語のカーネルがある。フロントエンドとカーネルの間に中継カーネルを挟むこともでき、<a href="https://64p.org/notes/lc4ri.html">LC4RI</a>のLC_wrapperはこれで出力の要約やログ保存をしている。</li>
<li><strong>フロントエンド</strong> — Classic Notebook、JupyterLab、Notebook 7。VS Codeの拡張や Google Colab、Amazon SageMaker なども Jupyter 系。</li>
<li><strong>JupyterHub</strong> — 多数のユーザーそれぞれに Notebook サーバを立ち上げて管理するマルチユーザー環境。</li>
</ul>


<h2>再現性の問題</h2>

<p>実行順を自由に選べるセル実行は探索的な作業には便利だが、隠れた状態・実行順の依存が残りやすい。</p>

<ul>
<li>Pimentelら(MSR 2019)はGitHub上の約140万Notebookを分析。実行を試みた有効な(Pythonバージョンと実行順が定義された)Notebook 863,878件のうち、<strong>エラーなく実行できたのは24.11%、同じ結果を再現したのは4.03%</strong>だった。</li>
<li>この結果からベストプラクティスを提案し、Notebook用linterの Julynter も作っている。</li>
</ul>


<p>LC4RIのLC_run_through(成功セルのFreeze)やnblineage(セルの系譜追跡)は、この「状態と実行順の管理」の問題に運用手順書の側から手当てしているもの、と見ることもできる。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/jupyter.html">#jupyter</a> <a class="note-tag" href="https://64p.org/notes/tags/python.html">#python</a> <a class="note-tag" href="https://64p.org/notes/tags/programming.html">#programming</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://en.wikipedia.org/wiki/Project_Jupyter">Project Jupyter - Wikipedia</a></li>
<li><a href="https://blog.jupyter.org/announcing-jupyter-notebook-7-8d6d66126dcf">Announcing Jupyter Notebook 7 | Jupyter Blog</a></li>
<li><a href="https://jupyter.org/enhancement-proposals/79-notebook-v7/notebook-v7.html">Build Jupyter Notebook v7 off of JupyterLab components (JEP 79)</a></li>
<li><a href="http://www.ic.uff.br/~leomurta/papers/pimentel2019a.pdf">Pimentel et al., A Large-scale Study about Quality and Reproducibility of Jupyter Notebooks (MSR 2019)</a></li>
</ul>

]]></description>
</item>
<item>
<title>LC4RI (Literate Computing for Reproducible Infrastructure)</title>
<link>https://64p.org/notes/lc4ri.html</link>
<guid isPermaLink="true">https://64p.org/notes/lc4ri.html</guid>
<pubDate>Sat, 26 Sep 2026 02:02:00 +0900</pubDate>
<description><![CDATA[<h1>LC4RI (Literate Computing for Reproducible Infrastructure)</h1>

<p>「再構築可能なインフラのための文芸的コンピューティング」(<a href="https://64p.org/notes/literate-programming.html">文芸的プログラミング</a>の発展形であるLiterate Computingをインフラ運用に適用したもの)。国立情報学研究所(NII)のクラウド運用チームが提唱・実践している、<a href="https://64p.org/notes/jupyter-notebook.html">Jupyter Notebook</a>を手順書兼作業証跡として使うインフラ運用の方法論。Notebookに「なぜやるか・前提・実行コマンド・結果・確認」を一緒に残し、実行可能で再現可能な手順書にする。</p>

<h2>考え方</h2>

<ul>
<li>公式の説明: 自動化された運用を live code として記述し、予測される結果・再現可能な結果を、技術者と非技術者の双方がナラティブ(物語)の形で共有する。</li>
<li><strong>Automated Operation と Automation を区別する</strong>。完全に蒸留された自動化(Automation)ではなく、常に人間がループの中にいて状況に縛られた「自動化された運用」を目指す。技術は人間の専門性を置き換えるのではなく補うもの、という立場。</li>
<li>CEDEC2019の講演では「過度な自動化への依存を防ぎ、チーム内でのノウハウ移転を促進する」ことで運用を強靭にする、という主張だった。</li>
<li>Qiitaの解説(yacchin1205)では、自分が理解していない部分をコード化すると問題発生時にかえって理解が難しくなる、と指摘。自動化(Automation)ではなく、チーム全体で対象システムへの理解を深める(Communication)方向を重視する。</li>
</ul>


<h2>役割分担: Jupyter + Ansible</h2>

<ul>
<li><a href="https://64p.org/notes/ansible.html">Ansible</a> — 対象システムへのコマンド実行を担当。</li>
<li>Jupyter Notebook — 実行結果を含めた「体験」を人間が読める形で保存する。単なる実行ログではなく、運用チームで知見を共有するコミュニケーション媒体。</li>
<li>すべての操作をコード化する必要はない、としている。代わりに以下を自然言語で書く:

<ul>
<li>前提条件の確認(OS、パッケージバージョンなど)</li>
<li>実行結果の確認(意図が満たされたとどう判断したか)</li>
<li>背景(このNotebookを実施するに至った経緯)</li>
</ul>
</li>
</ul>


<h2>成熟度の3段階(Qiita解説より)</h2>

<ol>
<li><strong>とにかく残す</strong> — 体験を記録して共有する。</li>
<li><strong>単純にする</strong> — 似たパターンを整理し、「健康な状態」を定義する(診断用Notebook)。症状と対処を体系化。</li>
<li><strong>適用範囲を広げる</strong> — 設計→設定の流れを明示し、環境依存値を分離して再利用性を上げる。</li>
</ol>


<h2>ツール群</h2>

<p>NII-cloud-operation がOSSとして公開しているJupyter拡張・カーネル。</p>

<table>
<thead>
<tr>
<th> ツール </th>
<th> 役割 </th>
</tr>
</thead>
<tbody>
<tr>
<td> LC_run_through </td>
<td> 見出しで折りたたんだセクション内のセルをワンクリックで一括実行。セルの状態を色付きブロックで表示(灰=未実行、緑=成功、ピンク=失敗)。成功したセルは自動で <strong>Freeze</strong> され、誤って再実行できなくなる。セルのロック(読み取り専用化)も可能 </td>
</tr>
<tr>
<td> LC_wrapper </td>
<td> IPythonカーネルとNotebookサーバの間に挟まる中継カーネル。<code>!!</code>で始まるセル(または<code>lc_wrapper_force=on</code>)の大量出力を要約して表示し、全出力は<code>.log/YYYYMMDD/</code>配下に保存してセルのメタデータにログパスを記録する。<code>lc_wrapper_regex</code>で重要なエラー行を要約に残し、<code>lc_wrapper_masking_pattern</code>でAPIキー等をマスクできる </td>
</tr>
<tr>
<td> multi_outputs </td>
<td> 通常は実行ごとに上書きされるセル出力を、タブとして複数保持(ピン留め)できる。ピン留めした出力と現在の出力のdiffも見られる </td>
</tr>
<tr>
<td> nblineage </td>
<td> Notebookと全セルに <em>meme</em> と呼ぶ追跡ID(UUID1)をメタデータとして振る。コピー・派生したNotebookにも引き継がれるので、手順書の系譜を追える </td>
</tr>
<tr>
<td> LC_index </td>
<td> Jupyterのファイル一覧画面に README.svg / README.md を表示する </td>
</tr>
<tr>
<td> sidestickies </td>
<td> 各セルにEtherpadやScrapboxを使った付箋(注釈)を付ける。Notebook本体のナラティブとは別のメタ・振り返り的コミュニケーション用 </td>
</tr>
<tr>
<td> nbsearch </td>
<td> 自分が作ったNotebookをキーワード・更新日時・memeで検索 </td>
</tr>
</tbody>
</table>


<p>実践環境をまとめたものとして OperationHub がある。小規模な運用チーム向けの、単一サーバ上のJupyterHub(ユーザーごとにDockerコンテナで分離、PAM認証、Notebook共有ディレクトリ)。</p>

<ul>
<li>LC_run_throughのFreezeは「一度成功した手順を二度流さない」ための仕組みで、冪等でない操作が混じる運用手順書と相性がよい。</li>
<li>LC_wrapperのログ保存は、Notebookを作業証跡(エビデンス)として扱うための仕組み。</li>
</ul>


<h2>歴史・関係者</h2>

<ul>
<li>NIIクラウド運用チーム。CEDEC2019講演者の長久勝(ライフマティックス/NII)、共同研究者として政谷好伸・谷沢智史・中川晋吾・合田憲人。</li>
<li>2019年 CEDEC「Jupyter Notebook が変える、あなたのチームの運用作業」。</li>
<li>2020年 Software Design 2020年5月号「Jupyter Notebookで解決するインフラ管理の手順書づくり LC4RI――再構築可能なインフラのための文芸的コンピューティングのすすめ」(監修: 長久勝・政谷好伸)。14のベストプラクティスを紹介。</li>
<li>NIIの情報処理技術セミナー(クラウド編)でも題材になっている。</li>
</ul>


<h2>考えたこと</h2>

<ul>
<li><a href="https://64p.org/notes/devops.html">DevOps</a>/SRE文脈で「<a href="https://64p.org/notes/toil.html">トイル</a>は自動化せよ」と言われがちなのに対して、あえて人間を中心に置く立場。完全自動化の手前にある「手順書+半自動実行」の層をきちんと道具化したもの、と捉えられる。</li>
<li><a href="https://64p.org/notes/configuration-management-tools.html">構成管理ツール</a>による宣言的なIaCが「あるべき状態」を記述するのに対し、LC4RIは「その場で何をやって何が起きたか」を記述する。補完関係。</li>
<li>実行可能な手順書という点では、最近のAIエージェントに渡す手順書(<a href="https://64p.org/notes/skill-md.html">SKILL.md</a>など)とも発想が近い。</li>
</ul>


<p><a class="note-tag" href="https://64p.org/notes/tags/devops.html">#devops</a> <a class="note-tag" href="https://64p.org/notes/tags/jupyter.html">#jupyter</a> <a class="note-tag" href="https://64p.org/notes/tags/infrastructure-as-code.html">#infrastructure-as-code</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://literate-computing.github.io/fastpages/introduction_en/">What is LC4RI?(en) | Literate Computing for Reproducible Infrastructure</a></li>
<li><a href="https://literate-computing.github.io/fastpages/tools_ja/">LC4RIツール(ja) | Literate Computing for Reproducible Infrastructure</a></li>
<li><a href="https://github.com/NII-cloud-operation/Jupyter-LC_run_through">NII-cloud-operation/Jupyter-LC_run_through</a></li>
<li><a href="https://github.com/NII-cloud-operation/Jupyter-LC_wrapper">NII-cloud-operation/Jupyter-LC_wrapper</a></li>
<li><a href="https://github.com/NII-cloud-operation/Jupyter-multi_outputs">NII-cloud-operation/Jupyter-multi_outputs</a></li>
<li><a href="https://github.com/NII-cloud-operation/Jupyter-LC_nblineage">NII-cloud-operation/Jupyter-LC_nblineage</a></li>
<li><a href="https://github.com/NII-cloud-operation/Jupyter-LC_index">NII-cloud-operation/Jupyter-LC_index</a></li>
<li><a href="https://github.com/NII-cloud-operation/sidestickies">NII-cloud-operation/sidestickies</a></li>
<li><a href="https://github.com/NII-cloud-operation/nbsearch">NII-cloud-operation/nbsearch</a></li>
<li><a href="https://github.com/NII-cloud-operation/OperationHub">NII-cloud-operation/OperationHub</a></li>
<li><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c9f1002670d8.html">CEDEC2019: Jupyter Notebook が変える、あなたのチームの運用作業</a></li>
<li><a href="https://gihyo.jp/dp/ebook/2020/978-4-297-11280-6">Software Design 2020年5月号 | 技術評論社</a></li>
<li><a href="https://qiita.com/yacchin1205/items/8bd1b79942418e0d0888">Jupyter+Ansibleを使ったインフラ運用の考え方2017 - Qiita</a></li>
<li><a href="https://qiita.com/manabuishiirb/items/ae60196fdcf86193b815">LC4RIに関するメモ - Qiita</a></li>
<li><a href="https://contents.nii.ac.jp/hrd/joho-karuizawa-cloud/2024">情報処理技術セミナー（クラウド編） | 国立情報学研究所</a></li>
</ul>

]]></description>
</item>
<item>
<title>herdrのソケットAPI</title>
<link>https://64p.org/notes/herdr-socket-api.html</link>
<guid isPermaLink="true">https://64p.org/notes/herdr-socket-api.html</guid>
<pubDate>Tue, 22 Sep 2026 01:06:00 +0900</pubDate>
<description><![CDATA[<h1>herdrのソケットAPI</h1>

<p><a href="https://64p.org/notes/herdr.html">herdr</a>が稼働中のセッションを外部から検査・操作させるために公開しているローカルAPI。<a href="https://64p.org/notes/herdr-plugins.html">プラグイン機構</a>やCLIの下にあるレイヤで、スクリプト・独自ツール・エージェントがここを叩く。</p>

<h2>3つのレイヤ</h2>

<p>ドキュメントは用途別に3レイヤを提示していて、「レイヤは同じコントロール面を共有する(The layers share the same control surface)」とされている。</p>

<table>
<thead>
<tr>
<th> レイヤ </th>
<th> 用途 </th>
</tr>
</thead>
<tbody>
<tr>
<td> Agent skill </td>
<td> エージェントにペイン内からherdrの使い方を教える → <a href="https://64p.org/notes/herdr-agent-skill.html">herdrのagent skillファイル</a> </td>
</tr>
<tr>
<td> CLIラッパー </td>
<td> シェルスクリプト、単純なオーケストレーション、人間によるデバッグ </td>
</tr>
<tr>
<td> 生のソケットAPI </td>
<td> 独自ツール、プロトコルクライアント、イベント購読者 </td>
</tr>
</tbody>
</table>


<p>「ほとんどの自動化はCLIラッパーから始めるべきで、生のソケットAPIはリクエスト/レスポンスを直接制御したい場合や、長寿命のイベント購読が必要な場合にだけ使う」という方針。<a href="https://64p.org/notes/herdr-plugins.html">プラグイン</a>も基本はCLI(<code>HERDR_BIN_PATH</code>)経由が推奨で、ソケットを直接叩くのは一段深い選択肢という位置づけになる。</p>

<h2>プロトコル</h2>

<p>改行区切りJSON(ndjson)。1行1リクエストで、レスポンスは同じ<code>id</code>を返す。</p>

<pre><code class="json">{"id":"req_1","method":"ping","params":{}}
{"id":"req_1","result":{"type":"pong"}}
</code></pre>

<p>エラーは<code>error</code>に<code>code</code>と<code>message</code>が入る。</p>

<pre><code class="json">{"id":"req_1","error":{"code":"not_found","message":"pane not found"}}
</code></pre>

<p>JSON-RPCではなく、独自のリクエスト/レスポンス形式。</p>

<h2>ソケットのパスと解決順</h2>

<p>トランスポートはUnixではドメインソケット、Windowsでは名前付きパイプ。</p>

<pre><code>~/.config/herdr/herdr.sock
~/.config/herdr/sessions/&lt;name&gt;/herdr.sock
</code></pre>

<p>どのソケットに繋ぐかは次の順で決まる。</p>

<ol>
<li>CLIの<code>--session &lt;name&gt;</code></li>
<li>環境変数<code>HERDR_SOCKET_PATH</code></li>
<li>環境変数<code>HERDR_SESSION=&lt;name&gt;</code></li>
<li>デフォルトセッションのソケット</li>
</ol>


<p>herdrが管理するペインには<code>HERDR_SOCKET_PATH</code> / <code>HERDR_ENV=1</code> / <code>HERDR_WORKSPACE_ID</code> / <code>HERDR_TAB_ID</code> / <code>HERDR_PANE_ID</code>が注入される。呼び出し側が渡した環境変数と衝突した場合はherdr側の値が優先される。</p>

<p>なおドキュメントには認証機構の記述が見当たらない。ローカルソケット前提の設計に見える。</p>

<h2>メソッド</h2>

<p>ドット記法で領域ごとに分かれている。網羅は<code>herdr api schema</code>に任せて、系統だけ挙げると、</p>

<ul>
<li><code>server.*</code> — <code>ping</code>、<code>server.stop</code>、<code>server.reload_config</code>、エージェントマニフェストの再読み込み</li>
<li><code>workspace.*</code> / <code>tab.*</code> — 作成・一覧・フォーカス・リネーム・移動・クローズ</li>
<li><code>pane.*</code> — 分割・移動・ズーム・リサイズなどのレイアウト系に加えて、<code>pane.send_text</code> / <code>pane.send_keys</code> / <code>pane.read</code> / <code>pane.wait_for_output</code>といった入出力系</li>
<li><code>agent.*</code> — <code>agent.list</code> / <code>agent.read</code> / <code>agent.prompt</code> / <code>agent.wait</code> / <code>agent.start</code>など、エージェント単位の操作</li>
<li><code>layout.*</code> — <code>layout.export</code> / <code>layout.apply</code></li>
<li><code>worktree.*</code> — <code>worktree.list</code> / <code>create</code> / <code>open</code> / <code>remove</code></li>
<li><code>plugin.*</code> — プラグインのリンク・有効化・アクション実行・ペイン開閉</li>
<li><code>events.subscribe</code> / <code>events.wait</code> / <code>session.snapshot</code></li>
</ul>


<p><code>pane.read</code>のソースには<code>visible</code> / <code>recent</code> / <code>recent-unwrapped</code> / <code>detection</code>があり、「今画面に出ているもの」と「最近の出力」を区別して読める。<code>pane.send_keys</code>はherdrのキー文字列(<code>enter</code>、<code>esc</code>、<code>ctrl+h</code>、<code>shift+tab</code>、<code>f1</code>、<code>minus</code>など)を受け付ける。</p>

<h2>スキーマはCLIから出せる</h2>

<pre><code class="sh">herdr api schema                              # サマリ
herdr api schema --json                       # 完全なJSON Schema
herdr api schema --output herdr-api.schema.json
</code></pre>

<p>バイナリに同梱されたスキーマが出るので、バージョンとズレない。リクエスト・成功レスポンス・エラーレスポンス・発火するイベント・購読イベントが対象。</p>

<h2>イベント購読</h2>

<p><code>events.subscribe</code>で購読すると、最初のレスポンスが購読の確認になり、以降はイベントが push されてくる(接続は開いたまま)。</p>

<pre><code class="json">{"id":"sub_1","method":"events.subscribe","params":{"subscriptions":[
  {"type":"pane.agent_status_changed","pane_id":"w1:p1","agent_status":"blocked"}
]}}
</code></pre>

<p>購読時点でフィルタを指定できるのがポイントで、上の例は「このペインのエージェントがblockedになったときだけ」という絞り込み。1回だけ待つ<code>events.wait</code>もある。</p>

<p>イベントは<code>workspace.*</code> / <code>tab.*</code> / <code>pane.*</code> / <code>layout.updated</code> / <code>worktree.*</code>の系統。エージェント運用で使いたくなるのはこのあたり。</p>

<ul>
<li><code>pane.agent_detected</code> — ペイン内でエージェントが検出された</li>
<li><code>pane.agent_status_changed</code> — 作業中・アイドル・入力待ちなどの状態が変わった</li>
<li><code>pane.output_matched</code> — 出力が指定パターンにマッチした</li>
<li><code>pane.exited</code> — プロセスが終了した</li>
<li><code>worktree.created</code> / <code>worktree.opened</code> / <code>worktree.removed</code></li>
</ul>


<p><a href="https://64p.org/notes/herdr-plus.html">herdr plus</a>がworktree作成時にレイアウトを流し込んでいるのは、この<code>worktree.created</code>を<a href="https://64p.org/notes/herdr-plugins.html">プラグイン機構</a>の<code>[[events]]</code>から拾っているもの。</p>

<h2>エージェントの状態を外から報告できる</h2>

<p>herdr本体はペインの出力からエージェントの状態を自動検出するが、ソケットAPI経由で<strong>外部から状態を申告する</strong>こともできる。herdrが知らない自作のエージェントやバッチ処理をサイドバーに乗せたい場合の口。</p>

<pre><code class="json">{"id":"req_1","method":"pane.report_agent","params":{
  "pane_id":"w1:p1","source":"custom:docs","agent":"docs-bot",
  "state":"working","message":"building docs"}}
</code></pre>

<p><code>state</code>は<code>idle</code> / <code>working</code> / <code>blocked</code> / <code>done</code> / <code>unknown</code>。ほかに<code>pane.report_agent_session</code>でセッションIDを紐付けたり、<code>pane.report_metadata</code>で表示用のタイトルや状態ラベル、TTLを渡したりできる。</p>

<p>サイドバーの見せ方自体も<code>agent.view.set</code>で宣言的に制御でき、<code>eq</code> / <code>in</code> / <code>exists</code> / <code>all</code> / <code>any</code> / <code>not</code>のフィルタと、<code>attention</code>や<code>state_change_seq</code>などでのソートを指定した「ビュー」を登録できる。</p>

<h2>ペインへの画像描画</h2>

<p><code>pane.graphics.*</code>でペインに画像を重ねられる。<code>pane.graphics.info</code>で能力(セルサイズ、ピクセルマウス対応、レイヤ上限16など)を取得し、<code>pane.graphics.set</code>にbase64のPNGと配置を渡す静的描画と、専用ソケットを開いてフレームごとにヘッダ＋生バイト列を流す<code>pane.graphics.stream</code>がある。形式は<code>png</code> / <code>rgb</code> / <code>rgba</code> / <code>bgra</code>。</p>

<p><a href="https://64p.org/notes/herdr-browser.html">herdr-browser</a>がペイン内にChromiumのスクリーンキャストをライブ表示できているのは、この層があるため。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/claude-code.html">#claude-code</a> <a class="note-tag" href="https://64p.org/notes/tags/tmux.html">#tmux</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://herdr.dev/docs/socket-api/">Socket API | herdr</a></li>
<li><a href="https://herdr.dev/docs/plugins/">Plugins | herdr</a></li>
</ul>

]]></description>
</item>
<item>
<title>herdrのagent skillファイル</title>
<link>https://64p.org/notes/herdr-agent-skill.html</link>
<guid isPermaLink="true">https://64p.org/notes/herdr-agent-skill.html</guid>
<pubDate>Tue, 22 Sep 2026 01:06:00 +0900</pubDate>
<description><![CDATA[<h1>herdrのagent skillファイル</h1>

<p><a href="https://64p.org/notes/herdr.html">herdr</a>がエージェント向けに配布している、herdr自身の操作方法を教えるMarkdownの指示書。<a href="https://64p.org/notes/herdr-socket-api.html">ソケットAPI</a>の3レイヤのうち、一番上の「Agent skill」レイヤに相当する。</p>

<p>「エージェントがherdrを操作するためのものがskillで、エージェントが人間にherdrを教えるためのものがguide」(The skill is for an agent operating Herdr; the guide is for an agent teaching a human)と役割が整理されている。</p>

<h2>入手方法</h2>

<pre><code class="sh">herdr --skill
</code></pre>

<p>バイナリに同梱された、そのリリースに対応するコピーが出力される。GitHub上のタグ付きパスからも取れる(<code>herdrdev/herdr</code>の<code>skills/herdr/SKILL.md</code>)。</p>

<p>グローバルに入れる場合は、</p>

<pre><code class="sh">npx skills add herdrdev/herdr --skill herdr -g
</code></pre>

<p>入れたうえでherdrの中からエージェントを起動する(<code>herdr claude</code>のように)。</p>

<h2>何をできるようになるか</h2>

<p>skillを読んだエージェントは、自分が置かれているherdrセッションを操作できるようになる。</p>

<ul>
<li>ワークスペース・タブ・ペイン、そして<strong>隣のエージェント</strong>を検査する</li>
<li>フォーカスを奪わずにペインを分割してコマンドを走らせる</li>
<li>ペインの出力や最近のログを読む</li>
<li>サーバーの起動、テストの完了、<strong>別のエージェントの完了</strong>を待つ</li>
<li>兄弟ペインに補助エージェントを起動する</li>
</ul>


<p>「隣のエージェントを見る」「別のエージェントの完了を待つ」「補助エージェントを起動する」あたりが、単なるターミナル操作と違う部分。エージェントがマルチプレクサ越しに他のエージェントを観測・起動できるので、herdrがオーケストレーションの土台になる。</p>

<h2><code>HERDR_ENV=1</code>によるガード</h2>

<p>skillの安全弁はここ。エージェントは操作の前に環境変数<code>HERDR_ENV=1</code>が設定されているかを確認し、<strong>設定されていなければ中断して「herdr管理下のペインで動いていない」と伝える</strong>よう指示されている。</p>

<p><code>HERDR_ENV=1</code>が立っているのは、herdrが管理するペインの中で動いている場合だけ。つまり「ローカルのherdrソケットに話しかけて構わない文脈かどうか」の判定を、この環境変数1つに集約している。skillを読んだエージェントがherdrの外で動いているときに、無関係なセッションを操作しに行かないための作り。</p>

<h2>考えたこと</h2>

<p><a href="https://64p.org/notes/herdr-plugins.html">プラグイン機構</a>が「CLI全体がプラグインAPI」という方針を採っているのと、このskillは同じ思想の延長にある。専用のSDKやツール定義を用意するのではなく、<strong>すでにあるCLIを説明する文書を配る</strong>ことでエージェント向けのインターフェイスを済ませている。MCPサーバーのようにプロトコルを立てる方向とは対照的なアプローチで、CLIが十分に整っているならこれで足りる、という判断に見える。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/claude-code.html">#claude-code</a> <a class="note-tag" href="https://64p.org/notes/tags/tmux.html">#tmux</a> <a class="note-tag" href="https://64p.org/notes/tags/ai-agent.html">#ai-agent</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://herdr.dev/docs/agent-skill/">Agent skill file | herdr</a></li>
<li><a href="https://herdr.dev/docs/socket-api/">Socket API | herdr</a></li>
</ul>

]]></description>
</item>
<item>
<title>herdrのプラグイン機構</title>
<link>https://64p.org/notes/herdr-plugins.html</link>
<guid isPermaLink="true">https://64p.org/notes/herdr-plugins.html</guid>
<pubDate>Tue, 22 Sep 2026 00:15:00 +0900</pubDate>
<description><![CDATA[<h1>herdrのプラグイン機構</h1>

<p><a href="https://64p.org/notes/herdr.html">herdr</a>本体はターミナルマルチプレクサとしての役割に絞られており、周辺機能はプラグインとして外に出す設計になっている。<a href="https://64p.org/notes/herdr-browser.html">herdr-browser</a>や<a href="https://64p.org/notes/herdr-plus.html">herdr plus</a>はいずれもこの機構の上に乗っている。</p>

<p>プラグインの実体は、<code>herdr-plugin.toml</code>というマニフェストと、herdrが起動できるコマンドを置いたディレクトリ。herdrはそれを<strong>別プロセスとして起動する</strong>だけなので、Bash・JavaScript・Lua・Rust・PowerShellなど、マシンで実行できるものなら言語は問わない。</p>

<h2>SDKが無い — CLIそのものがAPI</h2>

<p>この機構の一番の特徴。専用のプラグインSDKは存在せず、</p>

<blockquote><p>The entire Herdr CLI is the plugin API: every command in the CLI reference is available to a plugin, and anything you can run as <code>herdr ...</code> yourself a plugin can run too.</p></blockquote>

<p>という方針になっている。プラグインは環境変数<code>HERDR_BIN_PATH</code>が指すherdrバイナリを呼び戻すことでherdrを操作する。Unixドメインソケットと Windows の名前付きパイプの差をherdr側が吸収してくれるため、プラグインの移植性はCLI経由の方が高い。</p>

<p>ホスト側(herdr)が責任を持つのは、インストール・マニフェスト検証・キーバインド・ペイン・イベント・呼び出しコンテキスト・ソケットアクセスといった土台の部分。</p>

<h2>マニフェストと拡張ポイント</h2>

<pre><code class="toml">id = "example.layout"
name = "Layout"
version = "0.1.0"
min_herdr_version = "0.7.0"
description = "Apply project layouts"
platforms = ["linux", "macos", "windows"]

[[build]]
command = ["npm", "ci"]

[[startup]]
command = ["node", "dist/restore.js"]

[[actions]]
id = "apply"
title = "Apply layout"
contexts = ["workspace"]
command = ["node", "dist/apply.js"]

[[events]]
on = "worktree.created"
command = ["herdr", "workspace", "list"]

[[panes]]
id = "board"
title = "Project board"
placement = "overlay"
command = ["herdr-board"]

[[link_handlers]]
id = "github-issue"
title = "Open GitHub issue"
pattern = "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$"
action = "apply"
</code></pre>

<p>必須フィールドは<code>id</code> / <code>name</code> / <code>version</code> / <code>min_herdr_version</code>。拡張ポイントは5種類。</p>

<ul>
<li><code>[[startup]]</code> — セッション復元後に一度だけ走る初期化フック。常駐サービスの供給ではない(監視・再起動はされない)</li>
<li><code>[[actions]]</code> — キーバインドやUIから呼べるコマンド。<code>herdr plugin action invoke</code>で叩ける。config側からは<code>type = "plugin_action"</code>でキーに割り当てる</li>
<li><code>[[events]]</code> — herdrのイベントに反応するフック。<code>on = "worktree.created"</code>のように書く。<a href="https://64p.org/notes/herdr-plus.html">herdr plus</a>がworktree作成時にレイアウトを流し込んでいるのはこれ</li>
<li><code>[[panes]]</code> — ペインとして開くTUI。<code>placement</code>に<code>overlay</code> / <code>popup</code> / <code>split</code> / <code>tab</code> / <code>zoomed</code>を指定できる</li>
<li><code>[[link_handlers]]</code> — ターミナル内のURLへの修飾クリックを正規表現でマッチさせ、アクションにルーティングする</li>
</ul>


<p><code>[[build]]</code>はインストール時に走るビルドコマンド。<code>platforms</code>で対象OSを絞れる。</p>

<h2>文脈は環境変数で渡ってくる</h2>

<p>プラグインのコマンドには、herdrから実行時の文脈が環境変数として注入される。</p>

<table>
<thead>
<tr>
<th> 変数 </th>
<th> 内容 </th>
</tr>
</thead>
<tbody>
<tr>
<td> <code>HERDR_BIN_PATH</code> </td>
<td> 呼び戻すherdrバイナリ </td>
</tr>
<tr>
<td> <code>HERDR_SOCKET_PATH</code> </td>
<td> ソケットAPIのパス </td>
</tr>
<tr>
<td> <code>HERDR_ENV=1</code> </td>
<td> herdr配下で動いている印 </td>
</tr>
<tr>
<td> <code>HERDR_PLUGIN_ID</code> / <code>HERDR_PLUGIN_ROOT</code> </td>
<td> 自分のIDとチェックアウト先 </td>
</tr>
<tr>
<td> <code>HERDR_PLUGIN_CONFIG_DIR</code> / <code>HERDR_PLUGIN_STATE_DIR</code> </td>
<td> 設定と状態の置き場 </td>
</tr>
<tr>
<td> <code>HERDR_PLUGIN_CONTEXT_JSON</code> </td>
<td> 呼び出し文脈のJSON </td>
</tr>
<tr>
<td> <code>HERDR_WORKSPACE_ID</code> / <code>HERDR_TAB_ID</code> / <code>HERDR_PANE_ID</code> </td>
<td> 取れる場合のみ </td>
</tr>
</tbody>
</table>


<p>ほかに、アクションには<code>HERDR_PLUGIN_ACTION_ID</code>、イベントフックには<code>HERDR_PLUGIN_EVENT</code>と<code>HERDR_PLUGIN_EVENT_JSON</code>、ペインには<code>HERDR_PLUGIN_ENTRYPOINT_ID</code>が渡る。</p>

<h2>下位レイヤとしてのソケットAPI</h2>

<p>CLIの下には、稼働中のherdrを直接叩く<a href="https://64p.org/notes/herdr-socket-api.html">ソケットAPI</a>がある。改行区切りJSON(ndjson)で1行1リクエスト、レスポンスは同じ<code>id</code>を返す。</p>

<pre><code class="json">{"id":"req_1","method":"ping","params":{}}
{"id":"req_1","result":{"type":"pong"}}
</code></pre>

<p>トランスポートはUnixではドメインソケット、Windowsでは名前付きパイプ。デフォルトは<code>~/.config/herdr/herdr.sock</code>で、名前付きセッションは<code>~/.config/herdr/sessions/&lt;name&gt;/herdr.sock</code>。</p>

<p>ドキュメントは「ほとんどの自動化はCLIラッパーから始めるべきで、生のソケットAPIはリクエスト/レスポンスを直接制御したい場合や、長寿命のイベント購読が必要な場合にだけ使う」としている。さらに上のレイヤとして、エージェントにherdrの操作方法を教える<a href="https://64p.org/notes/herdr-agent-skill.html">agent skillファイル</a>がある。</p>

<h2>インストールと開発</h2>

<pre><code class="sh"># GitHubから入れる。リポジトリに複数プラグインがあればサブディレクトリまで指定
herdr plugin install owner/repository
herdr plugin install owner/repository/subdir

# ローカル開発用。ビルドコマンドをスキップする
herdr plugin link /path/to/plugin
</code></pre>

<p>インストールはクローン → プレビュー表示 → ビルドコマンド実行 → 登録、という流れ。これらのCLIはherdrサーバーが起動していなくてもレジストリに書き込み、次回起動時に読み込まれる。</p>

<p>躓きやすい点。</p>

<ul>
<li>コマンドは<strong>argv配列</strong>で、シェル展開は行われない</li>
<li><strong>自動更新の仕組みが無い</strong>。更新したければ入れ直す</li>
<li>認証情報はチェックアウト先ではなく<code>HERDR_PLUGIN_CONFIG_DIR</code>に置く。GitHubからの再インストールでチェックアウトは置き換わるため</li>
</ul>


<h2>サンドボックスは無い</h2>

<p>プラグインは自分の権限でそのまま動く普通のコードで、herdr CLIの全機能を呼べる。ドキュメントも「herdrはプラグインが何をするかをレビューもサンドボックス化もしない。サードパーティのプラグインは作者から来るものであってherdrから来るものではないので、各自で検証し、自己責任で動かすこと」と明言している。エディタ拡張やシェルスクリプトと同じ姿勢で読んでから入れるべき、という位置づけ。</p>

<p><a class="note-tag" href="https://64p.org/notes/tags/claude-code.html">#claude-code</a> <a class="note-tag" href="https://64p.org/notes/tags/tmux.html">#tmux</a></p>

<h2>出典</h2>

<ul>
<li><a href="https://herdr.dev/docs/plugins/">Plugins | herdr</a></li>
<li><a href="https://herdr.dev/docs/socket-api/">Socket API | herdr</a></li>
<li><a href="https://github.com/herdrdev/herdr/blob/master/docs/versions/0.8.0/website/src/content/docs/plugins.mdx">herdr/docs/&hellip;/plugins.mdx - GitHub</a></li>
<li><a href="https://flaviocopes.com/herdr-plugins/">A practical guide to Herdr plugins - Flavio Copes</a></li>
</ul>

]]></description>
</item>
<item>
<title>OnceLock (Rust)</title>
<link>https://64p.org/notes/rust-oncelock.html</link>
<guid isPermaLink="true">https://64p.org/notes/rust-oncelock.html</guid>
<pubDate>Mon, 21 Sep 2026 23:33:00 +0900</pubDate>
<description><![CDATA[<h1>OnceLock (Rust)</h1>

<p><code>std::sync::OnceLock&lt;T&gt;</code> は「一度だけ書き込める、スレッドセーフなセル」。Rust 1.70.0 で安定化された。<code>static</code> に置けるので、グローバルな遅延初期化を外部クレートなしで書くための標準的な手段になっている。 <a class="note-tag" href="https://64p.org/notes/tags/rust.html">#rust</a> <a class="note-tag" href="https://64p.org/notes/tags/並行処理.html">#並行処理</a></p>

<p>中身は最初は空で、どのスレッドからでも一度だけ値をセットできる。セットされて以降は不変の <code>&amp;T</code> として読めるだけになる。シングルスレッド専用版は <code>std::cell::OnceCell</code>。</p>

<h2>典型的な使い方</h2>

<pre><code class="rust">use std::sync::OnceLock;

static CONFIG: OnceLock&lt;Config&gt; = OnceLock::new();

fn config() -&gt; &amp;'static Config {
    CONFIG.get_or_init(|| Config::load_from_env())
}
</code></pre>

<p><code>OnceLock::new()</code> が const fn なので <code>static</code> の初期化子に書ける。<code>get_or_init</code> は複数スレッドが同時に呼んでもクロージャの実行は1回だけで、他のスレッドは初期化完了までブロックしてから同じ参照を受け取る。</p>

<p>公式ドキュメントの例:</p>

<pre><code class="rust">use std::sync::OnceLock;

static CELL: OnceLock&lt;usize&gt; = OnceLock::new();
assert!(CELL.get().is_none());

std::thread::spawn(|| {
    let value = CELL.get_or_init(|| 12345);
    assert_eq!(value, &amp;12345);
})
.join()
.unwrap();

assert_eq!(CELL.get(), Some(&amp;12345));
</code></pre>

<h2>主なメソッド</h2>

<table>
<thead>
<tr>
<th> メソッド </th>
<th> 挙動 </th>
</tr>
</thead>
<tbody>
<tr>
<td> <code>get()</code> </td>
<td> <code>Option&lt;&amp;T&gt;</code>。ブロックしない </td>
</tr>
<tr>
<td> <code>set(v)</code> </td>
<td> <code>Result&lt;(), T&gt;</code>。すでに入っていたら渡した値が <code>Err</code> で返ってくる </td>
</tr>
<tr>
<td> <code>get_or_init(f)</code> </td>
<td> 未初期化なら <code>f()</code> で初期化して <code>&amp;T</code> を返す </td>
</tr>
<tr>
<td> <code>get_mut()</code> </td>
<td> <code>&amp;mut self</code> 経由で <code>Option&lt;&amp;mut T&gt;</code> </td>
</tr>
<tr>
<td> <code>take()</code> </td>
<td> <code>&amp;mut self</code> 経由で中身を抜いて未初期化に戻す </td>
</tr>
<tr>
<td> <code>wait()</code> </td>
<td> 初期化されるまでブロックして <code>&amp;T</code>（1.86.0で安定化）。クロージャを取らず観測するだけ </td>
</tr>
<tr>
<td> <code>into_inner()</code> </td>
<td> 消費して <code>Option&lt;T&gt;</code> </td>
</tr>
</tbody>
</table>


<p><code>&amp;mut self</code> を要求する <code>get_mut</code>/<code>take</code> は、排他参照が取れている＝他スレッドと共有されていないことがコンパイル時に保証されるので、同期なしで中身をいじれるという理屈。</p>

<h2>poisoning がない</h2>

<p><code>Mutex</code> と違い <code>OnceLock</code> は poisoning しない。<code>get_or_init</code> に渡したクロージャがパニックしても、セルは未初期化のまま残り、次に呼んだスレッドがもう一度初期化を試みる。</p>

<p>対して後述の <code>LazyLock</code> は初期化クロージャがパニックすると<strong>恒久的に poisoned</strong> になり、以降のアクセスはすべてパニックする。初期化が失敗しうる場合の挙動がまったく違うので注意。</p>

<h2>LazyLock・Once との使い分け</h2>

<p>Rust 1.80.0 では <code>std::sync::LazyLock</code> も入った。</p>

<pre><code class="rust">use std::sync::LazyLock;

static CONFIG: LazyLock&lt;Config&gt; = LazyLock::new(|| Config::load_from_env());
// *CONFIG でアクセスすれば初回に自動で初期化される
</code></pre>

<ul>
<li><strong>初期化ロジックが宣言時に確定している</strong>なら <code>LazyLock</code>。格納場所と初期化処理を1箇所にまとめられ、<code>Deref</code> 経由の初回アクセスで自動的に走る。公式ドキュメントも「多くのケースで static には <code>LazyLock</code> のほうが簡潔」としている。</li>
<li><strong>初期化に実行時の値が必要</strong>（CLIオプションで組み立てた設定、あとから渡されるDBハンドルなど）な場合は <code>LazyLock::new(|| ...)</code> のクロージャに外から引数を渡せないので <code>OnceLock</code> + <code>get_or_init</code> / <code>set</code> を使う。初期化のタイミングを明示的に制御したい場合も同様。</li>
<li><code>std::sync::Once</code> は「値を持たない、処理を1回だけ実行する」ことだけを保証するプリミティブ。値を保持したいなら <code>OnceLock</code> を使う。</li>
</ul>


<p><code>OnceLock</code>/<code>LazyLock</code> はもともと外部クレート <code>once_cell</code>（および <code>lazy_static!</code> マクロ）が担っていた役割を標準ライブラリに取り込んだもので、<a href="https://rust-lang.github.io/rfcs/2788-standard-lazy-types.html">RFC 2788 &ldquo;standard lazy types&rdquo;</a> がその提案にあたる。新しく書くコードで <code>lazy_static</code> を持ち込む理由はほぼなくなった。</p>

<h2>出典</h2>

<ul>
<li><a href="https://doc.rust-lang.org/std/sync/struct.OnceLock.html">OnceLock in std::sync - Rust</a></li>
<li><a href="https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html">LazyLock in std::sync - Rust</a></li>
<li><a href="https://rust-lang.github.io/rfcs/2788-standard-lazy-types.html">RFC 2788: standard lazy types - The Rust RFC Book</a></li>
</ul>

]]></description>
</item>
</channel>
</rss>
