[{"data":1,"prerenderedAt":979},["ShallowReactive",2],{"content:\u002Fja\u002Fprojects\u002Fmydb\u002Fmydb2":3,"series:content_ja":261},{"id":4,"title":5,"authorship":6,"body":7,"categories":232,"date":234,"description":235,"draft":236,"extension":237,"image":238,"meta":239,"navigation":241,"path":242,"permalink":243,"published":243,"readingTime":244,"recommend":243,"references":243,"seo":249,"seoDescription":250,"seoTitle":243,"sitemap":251,"stem":252,"tags":253,"type":259,"__hash__":260},"content_ja\u002Fposts\u002Fprojects\u002Fmydb\u002Fmydb2.md","MYDB 2. 参照カウント方式のキャッシュ基盤と共有バイト配列","human-only",{"type":8,"value":9,"toc":222},"minimark",[10,22,26,29,35,38,41,44,49,52,55,63,76,79,84,87,94,97,100,106,116,119,125,131,137,140,146,149,155,158,164,167,173,176,179,182,185,190,193,201,204,207,210,213,219],[11,12,13,14,21],"p",{},"この章で扱うコードはすべて",[15,16,20],"a",{"href":17,"rel":18},"https:\u002F\u002Fgithub.com\u002FCN-GuoZiyang\u002FMYDB\u002Ftree\u002Fmaster\u002Fsrc\u002Fmain\u002Fjava\u002Ftop\u002Fguoziyang\u002Fmydb\u002Fbackend\u002Fcommon",[19],"nofollow","backend\u002Fcommon","にあります。",[23,24,25],"h3",{"id":25},"はじめに",[11,27,28],{},"この章からは、MYDBの最下層のモジュールであるデータマネージャーについて見ていきます。",[30,31,32],"blockquote",{},[11,33,34],{},"DMはデータベースのDBファイルとログファイルを直接管理します。主な役割は、1）DBファイルをページ単位で管理してキャッシュすること、2）エラー発生時にログから復旧できるようログファイルを管理すること、3）DBファイルをDataItemとして抽象化して上位モジュールに提供し、そのキャッシュも行うことです。",[11,36,37],{},"DMの役割は、大きく2つにまとめられます。1つは上位モジュールとファイルシステムの間の抽象化層で、下に向けてはファイルを直接読み書きし、上に向けてはデータを包んで提供します。もう1つはログ機能です。",[11,39,40],{},"上向きにも下向きにもキャッシュを提供し、メモリ上の操作で効率を確保している点に注目してください。",[23,42,43],{"id":43},"参照カウント方式のキャッシュ基盤",[45,46,48],"h4",{"id":47},"なぜlruではないのか","なぜLRUではないのか？",[11,50,51],{},"ページ管理にもデータ項目（DataItem）の管理にもキャッシュが必要なので、ここでは汎用的なキャッシュ基盤を設計します。",[11,53,54],{},"ここまで読むと、「とても先進的な」LRUを使わず、なぜ参照カウント方式なのかと思うかもしれません。",[11,56,57,58,62],{},"まずキャッシュのインターフェースから考えます。LRUなら",[59,60,61],"code",{"code":61},"get(key)","だけ用意すればよく、キャッシュがいっぱいになったときに自動的に追い出せます。ですが、こんな場面を想像してください。キャッシュがいっぱいになって、あるリソースが追い出されました。その直後、上位モジュールがリソースを保存元へ強制的に書き戻そうとします。それが、たった今追い出されたリソースでした。上位モジュールから見ると、データがキャッシュから消えています。さて、保存元への書き戻しは必要なのでしょうか。",[64,65,66,70,73],"ol",{},[67,68,69],"li",{},"書き戻さない。いつ追い出されたのかわからず、その後データ項目が変更されたかどうかもわかりません。非常に危険です。",[67,71,72],{},"書き戻す。追い出されたときと今のデータが同じなら、無駄な書き戻しになります。",[67,74,75],{},"キャッシュへ戻して、次に追い出すときに書き戻す。一見解決したようですが、キャッシュはすでにいっぱいです。戻すには別のリソースを追い出す必要があり、キャッシュのスラッシングを招くおそれがあります。",[11,77,78],{},"もちろん、リソースの最終更新時刻と、キャッシュから追い出した時刻を記録することもできます。でも……。",[30,80,81],{},[11,82,83],{},"必要もないのに存在者を増やしてはならない。――オッカムの剃刀",[11,85,86],{},"根本の問題は、LRUではリソースの追い出しを制御できず、上位モジュールもそれを把握できないことです。参照カウント方式なら、この問題を解決できます。上位モジュールが明示的に参照を解放し、どのモジュールもそのリソースを使っていないと確認できたときにだけ、キャッシュから追い出します。",[11,88,89,90,93],{},"これが参照カウント方式です。上位モジュールがリソースを使わなくなったときに参照を解放するため、",[59,91,92],{"code":92},"release(key)","を追加します。参照数が0になると、キャッシュからそのリソースを追い出します。",[11,95,96],{},"一方、キャッシュがいっぱいになっても、参照カウント方式では自動で空きを作れません。この場合は、そのままエラーにします。JVMでいきなりOOMになるようなものです。",[45,98,99],{"id":99},"実装",[11,101,102,105],{},[59,103,104],{"code":104},"AbstractCache\u003CT>","は抽象クラスで、具体的な処理を実装クラスに任せる2つの抽象メソッドを持ちます。",[107,108,114],"pre",{"className":109,"code":111,"language":112,"meta":113},[110],"language-java","\u002F**\n * 当资源不在缓存时的获取行为\n *\u002F\nprotected abstract T getForCache(long key) throws Exception;\n\u002F**\n * 当资源被驱逐时的写回行为\n *\u002F\nprotected abstract void releaseForCache(T obj);\n","java","",[59,115,111],{"__ignoreMap":113},[11,117,118],{},"参照カウントなので、通常のキャッシュ機能に加えて参照数を管理します。さらに、複数スレッドに対応するため、どのリソースを保存元から取得中かも記録する必要があります。取得には比較的時間がかかるためです。そこで、次の3つのMapを使います。",[107,120,123],{"className":121,"code":122,"language":112,"meta":113},[110],"private HashMap\u003CLong, T> cache;                     \u002F\u002F 实际缓存的数据\nprivate HashMap\u003CLong, Integer> references;          \u002F\u002F 资源的引用个数\nprivate HashMap\u003CLong, Boolean> getting;             \u002F\u002F 正在被获取的资源\n",[59,124,122],{"__ignoreMap":113},[11,126,127,130],{},[59,128,129],{"code":129},"get()","でリソースを取得するときは、まず無限ループに入り、キャッシュからの取得を繰り返し試みます。最初に、別のスレッドがそのリソースを保存元から取得中かを確認します。取得中なら、少し待ってからもう一度確認します（笑）。",[107,132,135],{"className":133,"code":134,"language":112,"meta":113},[110],"while(true) {\n    lock.lock();\n    if(getting.containsKey(key)) {\n        \u002F\u002F 请求的资源正在被其他线程获取\n        lock.unlock();\n        try {\n            Thread.sleep(1);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n            continue;\n        }\n        continue;\n    }\n    ...\n}\n",[59,136,134],{"__ignoreMap":113},[11,138,139],{},"すでにキャッシュにあれば、そのまま返せます。参照数を1増やすのを忘れずに。なければ、キャッシュに空きがあることを確認してgettingに登録し、このスレッドが保存元から取得を始めることを示します。",[107,141,144],{"className":142,"code":143,"language":112,"meta":113},[110],"while(true) {\n    if(cache.containsKey(key)) {\n        \u002F\u002F 资源在缓存中，直接返回\n        T obj = cache.get(key);\n        references.put(key, references.get(key) + 1);\n        lock.unlock();\n        return obj;\n    }\n\n    \u002F\u002F 尝试获取该资源\n    if(maxResource > 0 && count == maxResource) {\n        lock.unlock();\n        throw Error.CacheFullException;\n    }\n    count ++;\n    getting.put(key, true);\n    lock.unlock();\n    break;\n}\n",[59,145,143],{"__ignoreMap":113},[11,147,148],{},"保存元からの取得は単純で、抽象メソッドを呼ぶだけです。取得が終わったら、gettingからkeyを削除します。",[107,150,153],{"className":151,"code":152,"language":112,"meta":113},[110],"T obj = null;\ntry {\n    obj = getForCache(key);\n} catch(Exception e) {\n    lock.lock();\n    count --;\n    getting.remove(key);\n    lock.unlock();\n    throw e;\n}\n\nlock.lock();\ngetting.remove(key);\ncache.put(key, obj);\nreferences.put(key, 1);\nlock.unlock();\n",[59,154,152],{"__ignoreMap":113},[11,156,157],{},"キャッシュの解放はもっと簡単です。referencesの値を1減らし、0になったら保存元へ書き戻して、関連するキャッシュ内の管理情報をすべて削除します。",[107,159,162],{"className":160,"code":161,"language":112,"meta":113},[110],"\u002F**\n * 强行释放一个缓存\n *\u002F\nprotected void release(long key) {\n    lock.lock();\n    try {\n        int ref = references.get(key)-1;\n        if(ref == 0) {\n            T obj = cache.get(key);\n            releaseForCache(obj);\n            references.remove(key);\n            cache.remove(key);\n            count --;\n        } else {\n            references.put(key, ref);\n        }\n    } finally {\n        lock.unlock();\n    }\n}\n",[59,163,161],{"__ignoreMap":113},[11,165,166],{},"キャッシュには安全に閉じる機能も必要です。閉じる際は、キャッシュ内のすべてのリソースを強制的に保存元へ書き戻します。",[107,168,171],{"className":169,"code":170,"language":112,"meta":113},[110],"lock.lock();\ntry {\n    Set\u003CLong> keys = cache.keySet();\n    for (long key : keys) {\n        release(key);\n        references.remove(key);\n        cache.remove(key);\n    }\n} finally {\n    lock.unlock();\n}\n",[59,172,170],{"__ignoreMap":113},[11,174,175],{},"これでシンプルなキャッシュ基盤ができました。ほかのキャッシュは、このクラスを継承して2つの抽象メソッドを実装すれば使えます。",[23,177,178],{"id":178},"共有バイト配列",[11,180,181],{},"ここで、Javaのちょっと困ったところに触れておきます。",[11,183,184],{},"Javaでは配列をオブジェクトとして扱い、メモリ上でもオブジェクトとして保存します。一方、CやC++、Goなどでは、配列をポインターで実装します。そのため、こんな言い方もあります。",[30,186,187],{},[11,188,189],{},"本物の配列があるのはJavaだけ。",[11,191,192],{},"ただ、このプロジェクトにとっては、あまりうれしい話ではありません。たとえばGoなら、次のように書けます。",[107,194,199],{"className":195,"code":197,"language":198,"meta":113},[196],"language-go","var array1 [10]int64\narray2 := array1[5:]\n","go",[59,200,197],{"__ignoreMap":113},[11,202,203],{},"この場合、array2はarray1の5番目の要素から最後の要素までと同じメモリ領域を共有します。2つの配列の長さが違っていてもです。",[11,205,206],{},"Javaではこれができません。高級言語って何なんでしょうね〜。",[11,208,209],{},"JavaでsubArrayのような操作をしても、内部ではコピーするだけで、同じメモリ領域を共有できません。",[11,211,212],{},"そこで、配列の使用可能な範囲を緩く定めるSubArrayクラスを書きました。",[107,214,217],{"className":215,"code":216,"language":112,"meta":113},[110],"public class SubArray {\n    public byte[] raw;\n    public int start;\n    public int end;\n\n    public SubArray(byte[] raw, int start, int end) {\n        this.raw = raw;\n        this.start = start;\n        this.end = end;\n    }\n}\n",[59,218,216],{"__ignoreMap":113},[11,220,221],{},"正直、かなり不格好な方法ですが、今のところはこれでしのぐしかありません。別の方法をご存じなら、下のコメントで教えてください。私だって、こんな不格好に書きたいわけではないのです \u002F(ㄒo ㄒ)\u002F~~",{"title":113,"searchDepth":223,"depth":223,"links":224},4,[225,227,231],{"id":25,"depth":226,"text":25},3,{"id":43,"depth":226,"text":43,"children":228},[229,230],{"id":47,"depth":223,"text":48},{"id":99,"depth":223,"text":99},{"id":178,"depth":226,"text":178},[233],"projects","2021-11-30 23:18:00","データマネージャー（DM）は上位モジュールとファイルシステムをつなぎ、ページとキャッシュを管理しながら、データの安全性と復旧を支えます。キャッシュには従来のLRUではなく参照カウント方式を採用し、汎用性と効率を高めて、この先のデータ操作の土台を作ります。",false,"md","https:\u002F\u002Fblog-img.774352199.xyz\u002FWdIGoG.webp",{"slots":240},{},true,"\u002Fprojects\u002Fmydb\u002Fmydb2",null,{"text":245,"minutes":246,"time":247,"words":248},"11 min read",10.395,623700,2079,{"title":5,"description":235},"MYDB向けの参照カウント式キャッシュを実装。並行ロード、明示的な解放、終了時の書き戻しを扱い、SubArrayで同じバイト配列の一部を共有する方法も説明します。",{"loc":242},"posts\u002Fprojects\u002Fmydb\u002Fmydb2",[254,255,256,257,258],"MYDB","Java","参照カウント","キャッシュ設計","共有メモリ","tech","0fMgo6GNIziKTF8b8_sV-UbIlvHMdf-PnrRxM0oUJKI",[262,280,297,315,332,351,369,386,404,420,437,453,469,485,502,520,535,552,566,583,601,618,633,650,666,685,702,718,736,750,768,786,802,817,831,846,861,876,880,894,908,922,937,951,965],{"categories":263,"date":265,"description":266,"image":267,"path":268,"readingTime":269,"recommend":243,"tags":274,"title":279,"type":259},[264],"daily","2024-09-01 22:03:10","子どもの頃からの胃腸の不調が大学時代には不思議と消えたものの、就職後の夜更かしと飲酒で再発。慢性胃炎との付き合いは一筋縄ではいきませんでした。吐き気や胃のむかつきが日常になり、何度か検査を受けて生活を振り返るうちに、ようやく腰を据えて治療に向き合うようになりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002F0Hr9l5.webp","\u002Fdaily\u002Fanti-chronic-gastritis",{"text":270,"minutes":271,"time":272,"words":273},"7 min read",6.485,389100,1297,[275,276,277,278],"慢性胃炎","受診記録","胃内視鏡検査","健康記録","慢性胃炎の治療記録",{"categories":281,"date":282,"description":283,"image":284,"path":285,"readingTime":286,"recommend":243,"tags":291,"title":296,"type":259},[264],"2022-04-11 00:13:13","『三体』では、劉慈欣が壮大な歴史を通して個人と集団の関係を描いています。西側の民主主義への疑念と、大多数の人々に運命を委ねることへの悲観が、三部作を貫いています。英雄たちが力を尽くしても、その努力は歴史の流れに押し流される。文化大革命から始まる物語に、少数の傑出した人物と平凡な大衆の対立を読み、人間性と社会について考えました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FLTzbFP.webp","\u002Fdaily\u002Fpeople-in-three-body",{"text":287,"minutes":288,"time":289,"words":290},"19 min read",18.495,1109700,3699,[292,293,294,295],"三体","劉慈欣","SF文学","読書ノート","『三体』における「大多数の人々」",{"categories":298,"date":299,"description":300,"image":301,"path":302,"readingTime":303,"recommend":243,"tags":308,"title":314,"type":259},[264],"2024-01-04 02:06:51","2024年の学習目標は、日本語をN2レベルに引き上げること、SICPとTAPLを最後までやり切ること、POSIXを完全に実装したカーネルを作ること、そしてブログのテーマを更新すること。どれも簡単ではありませんが、今年取り組む方向は決まりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FV3rSQC.webp","\u002Fdaily\u002Fplan2024",{"text":304,"minutes":305,"time":306,"words":307},"1 min read",0.345,20700,69,[309,310,311,312,313],"年間計画","日本語学習","SICP","TAPL","オペレーティングシステム","2024年の学習計画",{"categories":316,"date":317,"description":318,"image":319,"path":320,"readingTime":321,"recommend":243,"tags":326,"title":331,"type":259},[264],"2024-09-28 16:26:00","ByteDanceで働いて3年。変化の速い環境で、時間まで加速したように感じながらも、どうにか心のバランスを保ってきました。杭州のオフィスのベランダから遠くの山を眺めていた入社当初を振り返り、仕事の壁や心境の変化、忙しさの中で自分のペースを探してきた日々を記します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhnCaht.webp","\u002Fdaily\u002Fwork-for-3-years",{"text":322,"minutes":323,"time":324,"words":325},"20 min read",19.73,1183800,3946,[327,328,329,330],"ByteDance","エンジニアのキャリア","仕事の振り返り","メンタルヘルス","ByteDanceで3年働きながら、ある程度の正気を保つことも不可能ではない",{"categories":333,"date":335,"description":336,"image":337,"path":338,"readingTime":339,"recommend":243,"tags":344,"title":350,"type":259},[334],"fiddling","2025-05-28 22:09:00","ブログをAstroに移行したところ、従来のGoogle Analytics導入方法では性能面が気になるようになりました。headタグにJavaScriptを直接追加してイベントを送ることはできますが、ページの性能に影響します。そこでpartytownでスクリプトをメインスレッドから切り離し、読み込みを妨げないようにしました。サンプルコードに手を加えることでGoogle Analyticsの導入に成功し、性能とアクセス解析を両立できました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FQ0w4RN.webp","\u002Ffiddling\u002Fastro-google-tag-manager",{"text":340,"minutes":341,"time":342,"words":343},"4 min read",3.455,207300,691,[345,346,347,348,349],"Astro","Google Analytics","Google Tag Manager","Partytown","アクセス解析","AstroにGoogle Analyticsを導入する（Tag Manager編）",{"categories":352,"date":353,"description":354,"image":355,"path":356,"readingTime":357,"recommend":362,"tags":363,"title":368,"type":259},[334],"2023-04-08 13:16:36","新しいプログラミング言語の設計は、難しくも面白い作業です。複雑なコンパイラ理論や機能の実装詳細をいったん脇に置き、コードがコンピューターのどこで動くかに注目すると、言語の作り方が見えてきます。RISC-VI命令セットを出発点に、基盤となる構造、階層化されたシステム、仮想マシンのモデルをたどり、言語の本質を考えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FuO420B.webp","\u002Ffiddling\u002Fchitchat-about-programming-language",{"text":358,"minutes":359,"time":360,"words":361},"28 min read",27.03,1621800,5406,2,[364,365,366,367],"プログラミング言語設計","型システム","コンパイラ設計","RISC-V","プログラミング言語についての雑談",{"categories":370,"date":371,"description":372,"image":373,"path":374,"readingTime":375,"recommend":223,"tags":379,"title":385,"type":259},[334],"2025-04-18 16:43:12","彼女が仕事で北京から上海に引っ越したので、回線の手配も手伝いました。ところが上海電信の500Mは杭州の1000Mより高く、なんとも納得がいきません。そこで上海での透過プロキシ、特定の通信の杭州経由での外部接続、両拠点のLAN相互接続を目指してネットワークを組むことにしました。杭州側はソフトウェアルーターと無線APのシンプルな構成で、普段から自宅経由で通信できる環境があり、次の挑戦に向けた準備はできています。","https:\u002F\u002Fblog-img.774352199.xyz\u002FO6cAGh.webp","\u002Ffiddling\u002Fcross-city-network-setup",{"text":245,"minutes":376,"time":377,"words":378},10.14,608400,2028,[380,381,382,383,384],"Tailscale","mihomo","拠点間ネットワーク","透過プロキシ","ホームネットワーク","上海と杭州の自宅ネットワークをつなぐ",{"categories":387,"date":388,"description":389,"image":390,"path":391,"readingTime":392,"recommend":243,"tags":397,"title":403,"type":259},[334],"2021-12-27 00:09:00","CSAPPの学習では実験が欠かせませんが、Linux環境の構築が壁になりがちです。とくに仮想マシンでは、インストール失敗、互換性、ネットワーク接続などの問題に悩まされます。Windows 10バージョン2004以降なら、WSL（Windows Subsystem for Linux）が有力な選択肢です。従来の仮想マシンの複雑さや性能面の負担を避けながら、Linux環境を手軽に利用できます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FvqOC7N.webp","\u002Ffiddling\u002Fcsapplab0",{"text":393,"minutes":394,"time":395,"words":396},"10 min read",9.585,575100,1917,[398,399,400,401,402],"CSAPP","WSL2","Linux","GDB","実験環境","CSAPP Labの環境構築",{"categories":405,"date":406,"description":407,"image":408,"path":409,"readingTime":410,"recommend":243,"tags":415,"title":419,"type":259},[334],"2024-07-13 17:49:00","Debianをサイドルーターに使うと、OpenWrtやLuCIに依存せず、より安定した柔軟な構成を作れます。Debianを直接設定することでシステムを細かく制御でき、GUIの制約や不安定さを避けられます。一般的なサイドルーター構成と比べて透過プロキシを安定して運用しやすく、性能や効率を重視する場合の選択肢になります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FpPRU5x.webp","\u002Ffiddling\u002Fdebian-as-bypass-router",{"text":411,"minutes":412,"time":413,"words":414},"18 min read",17.525,1051500,3505,[416,417,381,418,383],"Debian","サイドルーター","AdGuard Home","Debianをサイドルーターにする",{"categories":421,"date":422,"description":423,"image":424,"path":425,"readingTime":426,"recommend":243,"tags":431,"title":436,"type":259},[334],"2024-08-16 23:53:00","FakeIPを使った透過プロキシ構成で、従来のサイドルーターの単一障害点、性能不足、複雑なポート転送を改善します。プロキシコアをsing-boxに変えることで、転送性能を高めながら設定も簡単にできます。対応プロトコルが豊富で、従来のClashより最適化も進んでいます。同じ構成はClashでも実現できますが、sing-boxは柔軟な選択肢になります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FS2HHD5.webp","\u002Ffiddling\u002Ffake-ip-based-transparent-proxy",{"text":427,"minutes":428,"time":429,"words":430},"14 min read",13.1,786000,2620,[432,433,383,434,435],"FakeIP","sing-box","ポリシーベースルーティング","トラフィック振り分け","FakeIPを使った透過プロキシの振り分け",{"categories":438,"date":439,"description":440,"image":441,"path":442,"readingTime":443,"recommend":243,"tags":448,"title":452,"type":259},[334],"2024-08-15 23:50:00","サイドルーターを導入すると、メインルーターのポート転送が効かなくなることがあります。ゲートウェイをサイドルーターに変えることで通信経路が変わり、メインルーターを前提とした転送が正常に動かなくなるためです。ゲートウェイはアドレスを変換して内部ネットワークの通信を外部へ転送し、各端末は外部との通信にこれを必要とします。この仕組みを理解すると、ポート転送の問題を解決しやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FmRqws9.webp","\u002Ffiddling\u002Ffix-port-forward-in-bypass-router",{"text":444,"minutes":445,"time":446,"words":447},"6 min read",5.155,309300,1031,[417,449,450,451],"ポート転送","NAT","ネットワークのトラブルシューティング","サイドルーター環境でポート転送が効かない問題を解決する",{"categories":454,"date":455,"description":456,"image":457,"path":458,"readingTime":459,"recommend":243,"tags":464,"title":468,"type":259},[334],"2023-02-02 23:24:55","春節の帰省列車で、Goをベアメタルで動かす記事を読み、低レベルのシステムインターフェースに興味が湧きました。実際に動く実装を見て、高級言語でOSを作る可能性に胸が躍ります。関連研究を調べると先行例も見つかり、積もった熱意は期待に満ちたプロジェクトへと変わりました。しかし、最後は思いどおりにはいきませんでした。","https:\u002F\u002Fblog-img.774352199.xyz\u002FxB1Ni5.webp","\u002Ffiddling\u002Fgo-os",{"text":460,"minutes":461,"time":462,"words":463},"12 min read",11.81,708600,2362,[465,367,313,466,467],"Go","ベアメタルプログラミング","ランタイム","失敗に終わったプロジェクト：楽しくなかった春節の7日間",{"categories":470,"date":471,"description":472,"image":473,"path":474,"readingTime":475,"recommend":243,"tags":480,"title":484,"type":259},[334],"2022-08-15 01:05:01","システムのリファクタリングで、階層ごとのエンティティ変換に苦労しました。ビュー層の商品VO、ドメイン層のentity、永続化層のPOは似ていても、型のわずかな違いで直接変換できず、ディープコピーが面倒になります。そこでリフレクションを使った汎用的な変換処理を実装し、大量のassemblerメソッドを減らして、保守性と柔軟性を高めることにしました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBlhm0I.webp","\u002Ffiddling\u002Fgolang-deepcopy-between-different-type",{"text":476,"minutes":477,"time":478,"words":479},"5 min read",4.14,248400,828,[465,481,482,483],"リフレクション","ディープコピー","構造体変換","Goで異なる型の構造体をディープコピーする",{"categories":486,"date":487,"description":488,"image":489,"path":490,"readingTime":491,"recommend":243,"tags":495,"title":501,"type":259},[334],"2025-03-31 23:51:00","Appleヘルスケアの心拍数を定期的にサーバーへ同期し、Grafanaで可視化して直感的に確認できるようにしました。Health Auto ExportのREST API機能でHTTPエンドポイントへデータを送り、InfluxDBに保存します。Grafanaのダッシュボードから、自分の心拍数の変化を追ったり分析したりできます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FF4qD2T.webp","\u002Ffiddling\u002Fheart-rate-to-grafana",{"text":340,"minutes":492,"time":493,"words":494},3.76,225600,752,[496,497,498,499,500],"Apple Watch","Health Auto Export","InfluxDB","Grafana","心拍数モニタリング","My Heart Beats for U：心拍数をGrafanaで可視化する",{"categories":503,"date":504,"description":505,"image":506,"path":507,"readingTime":508,"recommend":512,"tags":513,"title":519,"type":259},[334],"2025-06-10 20:18:00","macOSとiPadOS 26では、新しいデザイン言語Liquid Glassが導入され、アイコンやウインドウの印象が一新されました。とくにiPadのアプリをウインドウで扱えるようになったことは、生産性向上のための端末へ進む大きな一歩です。一方、透明なコントロールセンターやLaunchpadの統合には賛否があり、使い勝手には改善の余地もあります。課題はありつつも、今後につながる更新だと感じました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FTPSaLE.webp","\u002Ffiddling\u002Fmacos-26-trial",{"text":270,"minutes":509,"time":510,"words":511},6.94,416400,1388,5,[514,515,516,517,518],"macOS 26","iPadOS 26","Liquid Glass","Apple Intelligence","OS使用感","macOS 26とiPadOS 26を試してみた",{"categories":521,"date":522,"description":523,"image":524,"path":525,"readingTime":526,"recommend":243,"tags":530,"title":534,"type":259},[334],"2026-06-11 10:00:00","今年もWWDCでmacOS 27の新しいApple Intelligenceが登場しました。macOS 26時代の回避方法はもう使えず、引き続きAppleとの知恵比べです。","https:\u002F\u002Fblog-img.774352199.xyz\u002FfOFucm.webp","\u002Ffiddling\u002Fmacos-27-apple-intelligence-chatgpt",{"text":393,"minutes":527,"time":528,"words":529},9.74,584400,1948,[531,517,532,533],"macOS 27","ChatGPT","中国本土向けMac","中国本土向けMacでApple Intelligenceを使う：地域変更からChatGPTの取り出しまで",{"categories":536,"date":537,"description":538,"image":539,"path":540,"readingTime":541,"recommend":243,"tags":545,"title":551,"type":259},[334],"2025-07-20 23:32:00","MoonTVはNext.jsとReactで作った動画集約プラットフォームで、連続ドラマなどを手軽に楽しむためのものです。LibreTVを改善しようとしたことが始まりで、数か月の開発を経て多くの関心と利用を集めています。Cursorのおかげで効率よく開発できた一方、複数環境への対応や複雑なデータ依存関係には苦労しました。ユーザーが増える中、フィードバックを受けて改善を続けています。","https:\u002F\u002Fblog-img.774352199.xyz\u002FnIeONi.webp","\u002Ffiddling\u002Fmoontv-vibe-coding",{"text":245,"minutes":542,"time":543,"words":544},10.98,658800,2196,[546,547,548,549,550],"MoonTV","LunaTV","Vibe Coding","Cursor","AI支援開発","MoonTV：Vibe Codingを試してみた",{"categories":553,"date":554,"description":555,"image":556,"path":557,"readingTime":558,"recommend":243,"tags":562,"title":565,"type":259},[334],"2024-10-07 16:51:00","BGPをもとに中国国内・国外のIPを振り分けることで、透過プロキシの効率と精度を高めます。国外の宛先をFakeIPで識別すれば、メインルーターでより適切に通信を振り分けられます。sing-boxのDNS設定も見直し、DNSクエリを柔軟かつ効率的に処理して、ネットワーク全体の使い勝手を改善します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FMOmM1s.webp","\u002Ffiddling\u002Fmore-accurate-chnroute",{"text":444,"minutes":559,"time":560,"words":561},5.75,345000,1150,[563,564,434,435],"BGP","IPアドレスデータベース","BGPで中国国内・国外IPの振り分けをより正確にする",{"categories":567,"date":568,"description":569,"image":570,"path":571,"readingTime":572,"recommend":243,"tags":577,"title":582,"type":259},[334],"2025-12-14 14:31:00","友人の一言からシミュレーターに興味が湧き、Microsoft Flight Simulatorを購入。地図やモデルはリアルタイム配信、アカウントは再ログインが必要、チュートリアルは見つけにくく、キーボード操作も難しい。結局フライトスティックを買い、Pico VRまで設定してようやく一通り体験できました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FlfhEuE.webp","\u002Ffiddling\u002Fmsfs2024-joystick-and-pico",{"text":573,"minutes":574,"time":575,"words":576},"9 min read",8.96,537600,1792,[578,579,580,581],"Microsoft Flight Simulator 2024","Thrustmaster TCA","PICO VR","フライトシミュレーション","Microsoft Flight Simulator 2024をあれこれ試す",{"categories":584,"date":585,"description":586,"image":587,"path":588,"readingTime":589,"recommend":243,"tags":594,"title":600,"type":259},[334],"2025-06-05 23:26:00","OnePlusからiPhoneへと何度も機種変更するうち、いじる楽しさからエコシステムへの依存へと関心が変わりました。最近、彼女の一言をきっかけに写真を改善しようとOPPO Find X8 Ultraを購入。Apple環境からの移行では、Androidアプリの質のばらつきと代替探しの難しさを改めて感じました。1か月をかけて、異なるプラットフォームの摩擦に折り合いをつけた記録です。","https:\u002F\u002Fblog-img.774352199.xyz\u002F19NIhZ.webp","\u002Ffiddling\u002Fone-month-using-android",{"text":590,"minutes":591,"time":592,"words":593},"15 min read",14.05,843000,2810,[595,596,597,598,599],"Android","OPPO","iOS","スマートフォン使用感","エコシステム移行","Androidに乗り換えて1か月",{"categories":602,"date":603,"description":604,"image":605,"path":606,"readingTime":607,"recommend":243,"tags":611,"title":617,"type":259},[334],"2026-05-11 22:43:00","GitHub Trendingで旅行計画ツールを見つけ、自分でも動かしたくなりました。どうせ新しいVPSを借りるなら、ついでにもう少し、いや、だいぶ色々入れてしまおうと。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBBdDWW.webp","\u002Ffiddling\u002Fone-trek-twenty-stacks",{"text":245,"minutes":608,"time":609,"words":610},10.34,620400,2068,[612,613,614,615,616],"TREK","Docker Compose","Dockge","VPS","セルフホスティング","TREKひとつのつもりが、20個のスタックに",{"categories":619,"date":620,"description":621,"image":622,"path":623,"readingTime":624,"recommend":243,"tags":628,"title":632,"type":259},[334],"2025-01-16 23:09:00","OPNsenseは、美しい画面と充実した機能を備えるオープンソースのファイアウォール・ルーターです。いくつかの構成を試した末に、透過プロキシやトラフィック振り分けでの可能性に気づきました。BGPベースの振り分けと組み合わせることで安全性と安定性を高められ、IPリストの自動更新で管理もしやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FxA8C1E.webp","\u002Ffiddling\u002Fopnsense-transparent-proxy",{"text":460,"minutes":625,"time":626,"words":627},11.38,682800,2276,[629,630,381,631,383,435],"OPNsense","FreeBSD","tun2socks","OPNsenseで透過プロキシとトラフィック振り分けを実現する",{"categories":634,"date":635,"description":636,"image":637,"path":638,"readingTime":639,"recommend":226,"tags":643,"title":649,"type":259},[334],"2025-03-15 20:35:00","構文解析では、ユーザー定義型名と通常の変数名を見分けることが課題になります。たとえば`a*b;`は算術式とも宣言とも解釈できます。とくに型指定子に関する文法規則によって変数名が型名と解釈され、正確さや読みやすさに影響します。初期化を伴わない変数宣言は多いため、この曖昧さはソースコードの随所に現れます。","https:\u002F\u002Fblog-img.774352199.xyz\u002F2VKHK9.webp","\u002Ffiddling\u002Fparser-type-variable-ambiguity",{"text":427,"minutes":640,"time":641,"words":642},13.58,814800,2716,[644,645,646,647,648],"構文解析","GLR","シンボルテーブル","スコープ","曖昧性解消","構文解析で型名と変数名の曖昧さを解消する",{"categories":651,"date":652,"description":653,"image":654,"path":655,"readingTime":656,"recommend":243,"tags":660,"title":665,"type":259},[334],"2023-05-24 17:51:09","RISC-Vツールチェーンをインストールするには、まずriscv-gnu-toolchainのソースを取得します。clone時に`--depth=1`を付けるとダウンロード量を減らせます。READMEのPrerequisitesを確認し、必要な依存関係をそろえてから進めます。Debianではコマンドで依存パッケージをまとめて導入できます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FrWNOKx.webp","\u002Ffiddling\u002Fspike-install",{"text":340,"minutes":657,"time":658,"words":659},3.89,233400,778,[367,661,662,663,664],"Spike","riscv-pk","クロスコンパイル","ツールチェーン","RISC-Vツールチェーンとエミュレーターのインストール",{"categories":667,"date":668,"description":669,"image":670,"path":671,"readingTime":672,"recommend":676,"tags":677,"title":684,"type":259},[334],"2026-09-09 23:59:00","これも一種のNTRですよね","https:\u002F\u002Fblog-img.774352199.xyz\u002FNDPUwc.webp","\u002Ffiddling\u002Fsteamdeck-switch-60fps",{"text":427,"minutes":673,"time":674,"words":675},13.905,834300,2781,7,[678,679,680,681,682,683],"Steam Deck","Nintendo Switch","EmuDeck","Eden","Lossless Scaling","フレーム生成","Steam Deckの第二の人生：Switchエミュレーター導入からフレーム補間で60FPSまで",{"categories":686,"date":687,"description":688,"image":689,"path":690,"readingTime":691,"recommend":243,"tags":696,"title":701,"type":259},[334],"2024-06-23 15:31:32","GFWは単に出口のゲートウェイを監視するのではなく、通信経路の脇から国際通信を傍受します。出入国するIPパケットをクラスタへ複製し、詳しく分析・フィルタリングする仕組みです。どこで何をしているかを理解することは、検閲回避の検討に欠かせません。ネットワーク構成を調べることで、遮断の経路や技術、対処方法が見えてきます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FsOpJuL.webp","\u002Ffiddling\u002Ftech-about-gfw",{"text":692,"minutes":693,"time":694,"words":695},"25 min read",24.975,1498500,4995,[697,698,699,700],"GFW","DNSポイズニング","TCP","インターネット検閲","GFWの仕組みを探る",{"categories":703,"date":704,"description":705,"image":706,"path":707,"readingTime":708,"recommend":243,"tags":712,"title":717,"type":259},[334],"2022-04-16 00:01:28","Javaでは`this`を使うことで、コンパイラの定数最適化が効かなくなる場合があります。このコード例の`ab1`と`ab2`は同じstatic final変数`s`を参照しているように見えますが、比較結果は異なります。静的変数を直接参照して文字列を連結する`ab1`に対し、`this`経由の`ab2`では同じ定数伝播の最適化が行われません。わずかな構文の違いが、コンパイル結果を変える例です。","https:\u002F\u002Fblog-img.774352199.xyz\u002FgKtkYe.webp","\u002Ffiddling\u002Fthis-in-javac-string-concat",{"text":340,"minutes":709,"time":710,"words":711},3.88,232800,776,[255,713,714,715,716],"javac","文字列連結","定数伝播","バイトコード","Javaのthisキーワードでコンパイル時の定数伝播が効かなくなる問題",{"categories":719,"date":720,"description":721,"image":722,"path":723,"readingTime":724,"recommend":243,"tags":729,"title":735,"type":259},[334],"2025-01-29 21:58:00","ひとこと投稿機能があれば、静的ブログの記事公開に伴う手間や心理的な負担を減らし、短い思いつきをいつでも共有できます。Cloudflare Workersでバックエンドを実装し、KVで投稿を保存・管理します。フロントエンドはVitePressにVueコンポーネントを埋め込み、投稿を手軽に表示してブログに動きと交流の場を加えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhZX6hr.webp","\u002Ffiddling\u002Fvitepress-memos-component",{"text":725,"minutes":726,"time":727,"words":728},"24 min read",23.345,1400700,4669,[730,731,732,733,734],"VitePress","Vue","Cloudflare Workers","Cloudflare KV","マイクロブログ","VitePressにひとこと投稿機能を実装する",{"categories":737,"date":738,"description":739,"image":740,"path":741,"readingTime":742,"recommend":243,"tags":746,"title":749,"type":259},[334],"2025-03-15 16:24:00","ある平凡な午後、Telegramの通知で魅力的なVPSプランを見つけました。中国電信CN2直結、帯域2.5Gという好条件です。IPv6付きで動画配信サービスの地域制限解除にも便利ですが、すべての通信をWARP経由にする必要はありません。以前のスクリプトは手軽な一方、速度と振り分けに不満があり、もっと柔軟な方法を探すことにしました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FMcjrrF.webp","\u002Ffiddling\u002Fvps-warp-ipv6",{"text":476,"minutes":743,"time":744,"words":745},4.09,245400,818,[747,748,615,434,435],"Cloudflare WARP","IPv6","VPSの特定の通信をWARP経由のIPv6で外に出す",{"categories":751,"date":752,"description":753,"image":754,"path":755,"readingTime":756,"recommend":760,"tags":761,"title":767,"type":259},[334],"2026-08-17 23:59:21","いじればいじるほど、もっといじりたくなります。年を取ってもまだまだ元気、まだまだ元気です。","https:\u002F\u002Fblog-img.774352199.xyz\u002FqfxB0h.webp","\u002Ffiddling\u002Fxiaomi17-root-and-hide-root",{"text":573,"minutes":757,"time":758,"words":759},8.83,529800,1766,6,[762,763,764,765,766],"Xiaomi 17","Bootloader","Android Root","ファームウェア書き換え","Rootの隠蔽","Xiaomi 17を普段使いに：ロック解除、ROM書き込み、root化とroot隠し",{"categories":769,"date":771,"description":772,"image":773,"path":774,"readingTime":775,"recommend":243,"tags":780,"title":785,"type":259},[770],"notes","2022-01-20 22:29:00","Lab 1では、masterとworkerという2つの主要な部分からなるMapReduceシステムを実装します。GoのRPCと並行プログラミングを十分に使いこなし、MapReduceの処理の流れも深く理解する必要があります。実装は2つの版を作り、mutexでロックする方式から、よりすっきりしたchannelによる明示的なロックを使わない方式へと改めました。後者のほうが設計もシンプルで分かりやすくなっています。実習を理解する鍵は、関連資料、特にフローチャートとその説明をしっかり読むことです。","https:\u002F\u002Fblog-img.774352199.xyz\u002FibVwPJ.webp","\u002Fnotes\u002F65840\u002Fmapreducelab",{"text":776,"minutes":777,"time":778,"words":779},"13 min read",12.39,743400,2478,[781,782,465,783,784],"MIT 6.5840","MapReduce","RPC","並行プログラミング","6.5840 Lab 1：MapReduce",{"categories":787,"date":788,"description":789,"image":790,"path":791,"readingTime":792,"recommend":243,"tags":796,"title":801,"type":259},[770],"2022-01-16 17:32:00","MapReduceは、大規模なデータセットの処理を簡単にするための効率的な並列計算モデルです。利用者はMapとReduceという2つの主要な関数を定義することで、複雑なタスクを簡単な操作に分解できます。データの分配やタスクの割り当てはフレームワークが自動で管理するため、開発者は低レベルの細部に気を取られず、アルゴリズムそのものに集中できます。分散システムで広く使われていることからも、その柔軟性と実用性が分かります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FApIDdC.webp","\u002Fnotes\u002F65840\u002Fmapreducepaper",{"text":573,"minutes":793,"time":794,"words":795},8.085,485100,1617,[782,797,798,799,800],"分散システム","論文ノート","並列計算","耐障害性","MapReduce論文を読む",{"categories":803,"date":804,"description":805,"image":806,"path":807,"readingTime":808,"recommend":243,"tags":812,"title":816,"type":259},[770],"2022-12-16 02:06:10","Lab 2Aでは、Raftのリーダー選出とハートビートを実装し、さまざまな厳しい条件でも任期の交代や選挙が正常に行われるようにします。実習全体は4段階からなり、この後に実装する分散KVストアの土台になります。明示的なロックを使わない設計によって、Raft構造体を簡潔にします。実習の手引きには必要な背景知識が載っていますが、前の実習と比べると参考資料に頼れる部分はほとんどなく、自力で実装することが重視されます。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fc11Uk4.webp","\u002Fnotes\u002F65840\u002Fraftlab2a",{"text":411,"minutes":809,"time":810,"words":811},17.515,1050900,3503,[781,813,465,814,815],"Raft","リーダー選出","分散合意","6.5840 Lab 2A：リーダー選出",{"categories":818,"date":819,"description":820,"image":821,"path":822,"readingTime":823,"recommend":243,"tags":828,"title":830,"type":259},[770],"2022-12-03 21:40:09","Raftは、ログレプリケーションの効率を高めるために設計された合意アルゴリズムです。複数のマシンからなるクラスタに適しており、一部のマシンが故障してもサービスを継続できます。複製状態機械モデルを使い、ログに命令の順序を記録することで、クラスタ内の各マシンが同じ状態に到達できるようにします。論文『In Search of an Understandable Consensus Algorithm』は、Raftの設計思想とPaxosとの比較を詳しく論じ、その理解しやすさを示すとともに、信頼できる大規模なソフトウェアシステムを構築するための土台を提供しています。この記事は、その中心的な概念と応用を理解するための読書メモです。","https:\u002F\u002Fblog-img.774352199.xyz\u002F7mmvIZ.webp","\u002Fnotes\u002F65840\u002Freftextendedpaper",{"text":824,"minutes":825,"time":826,"words":827},"30 min read",29.245,1754700,5849,[813,815,829,798],"ログ複製","Raft論文を読む",{"categories":832,"date":833,"description":834,"image":835,"path":836,"readingTime":837,"recommend":841,"tags":842,"title":845,"type":259},[233],"2021-11-27 14:43:00","MYDBは、データベースの基本原理を学び、実装してみるための個人プロジェクトです。空き時間を使い、半月あまりかけて作りました。大学のデータベースシステムの授業で基礎には触れたものの、インターン中は授業を口実にサボってばかりでした。面接で正直に答えても大きな問題にはなりませんでしたが、それをきっかけに自分の知識を見直し、実際に手を動かして学ぼうと考えるようになりました。そうして生まれたのがこのプロジェクトです。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fxfci2J.webp","\u002Fprojects\u002Fmydb\u002Fmydb0",{"text":573,"minutes":838,"time":839,"words":840},8.03,481800,1606,1,[254,255,843,844],"データベース実装","データベースアーキテクチャ","MYDB 0. プロジェクト構成と、先に伝えておきたいこと",{"categories":847,"date":848,"description":849,"image":850,"path":851,"readingTime":852,"recommend":243,"tags":857,"title":860,"type":259},[233],"2021-11-28 16:10:00","MYDBではXIDファイルでトランザクションを管理します。各トランザクションには1から増える一意のXIDがあり、XID 0は常にコミット済みのスーパートランザクションです。TransactionManagerがこのファイルを管理し、実行中・コミット済み・中止済みという3つの状態を記録します。この仕組みにより状態を正確に照会・管理でき、システムの安定性と信頼性を支えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FH4zZAK.webp","\u002Fprojects\u002Fmydb\u002Fmydb1",{"text":853,"minutes":854,"time":855,"words":856},"8 min read",7.42,445200,1484,[254,255,858,859],"トランザクション管理","XID","MYDB 1. まずはシンプルなTMから",{"categories":862,"date":863,"description":864,"image":865,"path":866,"readingTime":867,"recommend":243,"tags":871,"title":875,"type":259},[233],"2021-12-25 18:26:00","MYDBはMySQLに似たC\u002FS構成を採用し、複数のクライアントがソケットでサーバーへ接続してSQLを実行し、結果を受け取れます。通信には専用のバイナリー形式を使いますが、実装を簡単にするならプレーンテキストも選択肢です。サーバーとクライアントの基本的な転送構造によって、データのやり取りと処理を行います。","https:\u002F\u002Fblog-img.774352199.xyz\u002FPAHrUZ.webp","\u002Fprojects\u002Fmydb\u002Fmydb10",{"text":444,"minutes":868,"time":869,"words":870},5.76,345600,1152,[254,255,872,873,874],"Socket","クライアントサーバー構成","通信プロトコル","MYDB 10. サーバー・クライアントの実装と通信プロトコル",{"categories":877,"date":234,"description":235,"image":238,"path":242,"readingTime":878,"recommend":243,"tags":879,"title":5,"type":259},[233],{"text":245,"minutes":246,"time":247,"words":248},[254,255,256,257,258],{"categories":881,"date":882,"description":883,"image":884,"path":885,"readingTime":886,"recommend":243,"tags":890,"title":893,"type":259},[233],"2021-12-05 15:28:00","DMはファイルシステムをページとして抽象化し、ページ単位で読み書きとキャッシュを行います。データページのデフォルトサイズは8Kで、大量の書き込みではサイズの調整によって性能を高められます。実装済みの汎用キャッシュ基盤を使い、ここではページ構造を具体的に定義して、効率よくページを管理します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FjlFC4E.webp","\u002Fprojects\u002Fmydb\u002Fmydb3",{"text":853,"minutes":887,"time":888,"words":889},7.14,428400,1428,[254,255,891,892],"データページ","キャッシュ管理","MYDB 3. データページのキャッシュと管理",{"categories":895,"date":896,"description":897,"image":898,"path":899,"readingTime":900,"recommend":243,"tags":904,"title":907,"type":259},[233],"2021-12-08 22:55:00","MYDBでは、クラッシュ後にデータを復旧できるよう、ログファイルが重要な役割を担います。DMは下位のデータを操作するたびにログを生成・記録し、連続したログ列を作ります。チェックサムと各操作の記録を含む所定のバイナリー形式で保存することで、再起動時にデータの状態を正確に再構築し、整合性と完全性を保ちます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FTRcbsj.webp","\u002Fprojects\u002Fmydb\u002Fmydb4",{"text":776,"minutes":901,"time":902,"words":903},12.685,761100,2537,[254,255,905,906],"データベースログ","クラッシュリカバリ","MYDB 4. ログファイルと復旧戦略",{"categories":909,"date":910,"description":911,"image":912,"path":913,"readingTime":914,"recommend":243,"tags":918,"title":921,"type":259},[233],"2021-12-11 15:16:00","ページインデックスはDM層の重要な構成要素です。各ページの空き容量をキャッシュすることで挿入処理を効率化し、上位モジュールが長い探索をせずに適切なページを素早く見つけられるようにします。実装ではデータ項目（DataItem）の抽象化とも密接に連携し、データベースの効率的な動作を支えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002F22PSG1.webp","\u002Fprojects\u002Fmydb\u002Fmydb5",{"text":393,"minutes":915,"time":916,"words":917},9.86,591600,1972,[254,255,919,920],"ページインデックス","データ管理","MYDB 5. ページインデックスとDMの実装",{"categories":923,"date":924,"description":925,"image":926,"path":927,"readingTime":928,"recommend":243,"tags":932,"title":936,"type":259},[233],"2021-12-18 14:58:00","VMは二相ロックでスケジュールの直列化可能性を保証し、多版型同時実行制御（MVCC）を導入して読み取りと書き込みの相互ブロックを解消します。また、データベース操作の競合を定義し、特に更新と読み取りの関係を整理することで、トランザクションの分離レベルを理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002F8YzotA.webp","\u002Fprojects\u002Fmydb\u002Fmydb6",{"text":590,"minutes":929,"time":930,"words":931},14.665,879900,2933,[254,255,933,934,935],"MVCC","トランザクション分離","二相ロック","MYDB 6. レコードのバージョンとトランザクション分離",{"categories":938,"date":939,"description":940,"image":941,"path":942,"readingTime":943,"recommend":243,"tags":947,"title":950,"type":259},[233],"2021-12-23 21:20:00","VMでは、MVCCに伴うバージョンの飛び越しとデッドロックに対処する必要があります。MYDBはトランザクションに印を付けるだけで取り消しやロールバックを行い、abortedなトランザクションのデータがほかへ影響しないようにします。この設計により並行処理の効率と信頼性を高め、従来の2PLで起こりがちなデッドロックを避けて、システム全体の安定性と性能を向上させます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBF3yDW.webp","\u002Fprojects\u002Fmydb\u002Fmydb7",{"text":460,"minutes":944,"time":945,"words":946},11.32,679200,2264,[254,255,948,949],"デッドロック検出","バージョン管理","MYDB 7. デッドロック検出とVMの実装",{"categories":952,"date":953,"description":954,"image":955,"path":956,"readingTime":957,"recommend":243,"tags":961,"title":964,"type":259},[233],"2021-12-24 21:01:00","MYDBはB+木によるクラスタ化インデックスを実装します。IMはバージョンマネージャー（VM）を経由せず、データマネージャー（DM）と直接やり取りし、インデックスデータをデータベースファイルへ直接書き込みます。この章では二分木インデックスの構造を詳しく説明し、葉フラグ、キー数、兄弟ノードの識別子など、インデックス検索の基盤となる要素を扱います。","https:\u002F\u002Fblog-img.774352199.xyz\u002Ff92X4o.webp","\u002Fprojects\u002Fmydb\u002Fmydb8",{"text":270,"minutes":958,"time":959,"words":960},6.53,391800,1306,[254,255,962,963],"B+木","データベースインデックス","MYDB 8. インデックス管理",{"categories":966,"date":967,"description":968,"image":969,"path":970,"readingTime":971,"recommend":243,"tags":975,"title":978,"type":259},[233],"2021-12-25 15:44:00","テーブルマネージャー（TBM）は、フィールドとテーブルの構造を管理します。ParserはSQL風の文を構造化して解析し、文に含まれる情報を対応するクラスへまとめることで、その後の操作を簡単にします。この章ではMYDBのSQL構文も紹介し、管理処理全体を理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FzOMyv5.webp","\u002Fprojects\u002Fmydb\u002Fmydb9",{"text":853,"minutes":972,"time":973,"words":974},7.99,479400,1598,[254,255,976,977],"SQL解析","テーブル管理","MYDB 9. フィールドとテーブルの管理",1789914059774]