[{"data":1,"prerenderedAt":1123},["ShallowReactive",2],{"content:\u002Fja\u002Ffiddling\u002Fparser-type-variable-ambiguity":3,"series:content_ja":405},{"id":4,"title":5,"authorship":6,"body":7,"categories":376,"date":378,"description":379,"draft":380,"extension":381,"image":382,"meta":383,"navigation":385,"path":386,"permalink":387,"published":387,"readingTime":388,"recommend":372,"references":387,"seo":393,"seoDescription":394,"seoTitle":387,"sitemap":395,"stem":396,"tags":397,"type":403,"__hash__":404},"content_ja\u002Fposts\u002Ffiddling\u002Fparser-type-variable-ambiguity.md","構文解析で型名と変数名の曖昧さを解消する","human-only",{"type":8,"value":9,"toc":368},"minimark",[10,14,27,30,40,55,58,61,64,92,98,106,112,138,150,153,156,159,163,166,174,181,184,190,193,204,215,218,243,246,264,281,296,300,303,309,312,318,330,341,350,353,359,362],[11,12,13],"h3",{"id":13},"導入",[15,16,17,18,22,23,26],"p",{},"構文解析段階でシンボルテーブルを持たない場合、ユーザー定義型名（typedef）と普通の変数名は見分けにくくなります。関数内の",[19,20,21],"code",{"code":21},"a*b;","は、aとbを掛けて結果を捨てる式とも、型",[19,24,25],{"code":25},"a*","の変数bを宣言する文とも解釈できます。",[15,28,29],{},"さらに、次の文法規則があります。",[31,32,37],"pre",{"className":33,"code":35,"language":36},[34],"language-text","declaration := declaration_specifiers SEMICOLON\ndeclaration_specifiers := type_specifier declaration_specifiers\ntype_specifier := INT\ntype_specifier := typedef_name\ntypedef_name := IDENTIFIER\n","text",[19,38,35],{"__ignoreMap":39},"",[15,41,42,43,46,47,50,51,54],{},"規則1は、識別子を指定する必要のない構造体の前方宣言によく使います。たとえば",[19,44,45],{"code":45},"struct Node;","は",[19,48,49],{"code":49},"struct Node","型の前方宣言です。しかしこの規則があるため、",[19,52,53],{"code":53},"int a;","も規則1で還元され、aが変数名ではなくユーザー定義型名と認識される可能性があります。初期化なしの変数宣言は頻出するので、1つのソースから文法を満たすASTが多数生まれます。意味解析でシンボルテーブルを持てば解決できますが、構文解析の段階でも小さなコストで処理し、意味解析に渡すASTを減らせます。",[11,56,57],{"id":57},"方針",[15,59,60],{},"型名と変数名の曖昧さは、GLRの実行中または実行後に簡易シンボルテーブルを使い、不正な分岐を刈り込むことで解消できます。最低限、変数名とユーザー定義型名を記録します。内側の変数名や型名が外側のシンボルを隠すこともあるので、スコープも追跡する必要があります。",[15,62,63],{},"やることは単純です。",[65,66,67,71,74,84],"ol",{},[68,69,70],"li",{},"シンボルテーブルを維持し、型定義と変数宣言を集める。",[68,72,73],{},"シンボルの追加時に、同じスコープに同名の変数宣言や型定義がないか確認する。",[68,75,76,79,80,83],{},[19,77,78],{"code":78},"primary_expression := IDENTIFIER","で還元した各ノードについて、",[19,81,82],{"code":82},"IDENTIFIER","が宣言済みで隠されていない変数名か確認する。",[68,85,86,79,89,91],{},[19,87,88],{"code":88},"typedef_name := IDENTIFIER",[19,90,82],{"code":82},"が定義済みで隠されていないユーザー定義型名か確認する。",[15,93,94,95,97],{},"定番の",[19,96,21],{"code":21},"で考えます。",[31,99,104],{"className":100,"code":102,"language":103,"meta":39},[101],"language-c","\u002F\u002F 例 1\ntypedef int a;\nfunc test_func()\n{\n\ta*b;\n}\n","c",[19,105,102],{"__ignoreMap":39},[31,107,110],{"className":108,"code":109,"language":103,"meta":39},[101],"\u002F\u002F 例 2\ntypedef int a;\nfunc test_func()\n{\n\tint a;\n\ta*b;\n}\n",[19,111,109],{"__ignoreMap":39},[15,113,114,115,117,118,120,121,124,125,127,128,131,132,134,135,137],{},"例1：",[19,116,21],{"code":21},"の解析時、スコープ1（最外層）にはユーザー定義型aがあり、スコープ2（関数内）にはシンボルがありません。型",[19,119,25],{"code":25},"の変数",[19,122,123],{"code":123},"b","の宣言と解釈するASTでは、aは",[19,126,88],{"code":88},"で還元されます。テーブルを確認するとaは確かにスコープ1のユーザー定義型なので、このASTを残します。変数",[19,129,130],{"code":130},"a","と変数",[19,133,123],{"code":123},"の乗算と解釈するASTでは、aは",[19,136,78],{"code":78},"で還元されます。変数aはテーブルにないので、このASTは破棄します。",[15,139,140,141,143,144,146,147,149],{},"例2：",[19,142,21],{"code":21},"の解析時、スコープ1にユーザー定義型a、スコープ2に変数aがあり、変数が型を隠しています。宣言と解釈するASTではaを",[19,145,88],{"code":88},"で還元しますが、このスコープのaは変数であって型ではないため、ASTを破棄します。乗算と解釈するASTではaを",[19,148,78],{"code":78},"で還元し、変数名であることが確認できるのでASTを残します。",[15,151,152],{},"完全なシンボルテーブルと違い、この簡易版はスコープ内で同種の変数が同名で宣言される問題を検査しません。ユーザー定義型名の重複は検査できます。前方宣言があるので同じ変数の宣言は複数回許されますが、初期化を含められるのは1回だけです。構文解析で初期化の有無を見分けるのは比較的コストが高いため、意味解析まで遅らせるのがおすすめです。型検査も同じ理由でこの段階では行いません。",[15,154,155],{},"GLR実行中に簡易テーブルを維持する場合、関数引数やforループの変数宣言の扱いが難しくなります。これらは実際には内側のスコープに属し、スコープの境界が波括弧と完全には一致しません。関数定義への還元は左右の波括弧をシフトした後でしかできないため、波括弧をシフトした時点で単純にスコープを操作できず、現在のシンボルスタック上の複数のシンボルを合わせて判断する必要があります。根本的な理由は、GLRが葉から根へASTをボトムアップに作ることです。下位ノードを先に処理するため、その周囲の文脈を把握できません。",[15,157,158],{},"GLRの実行後にASTの森を走査し、1本ずつ検査して除外する方法はずっと簡単です。実行中の枝刈りができず、時間と空間の計算量は増えますが、利点は実装が簡単、実装が簡単、そして実装が簡単なことです。実際には両方を組み合わせられます。実行中の枝刈りは安価で、成功すれば後で調べるASTを減らせます。実行後の検査でこの曖昧さは必ず解消できるので、実行中は「不正な枝を見逃しても、正しい枝を誤って切らない」を守ります。",[11,160,162],{"id":161},"ast構築中","AST構築中",[15,164,165],{},"シンボルのシフトや還元時にノードへ情報を保存して上へ伝えると、後でトップダウンに処理するときすぐ取り出せます。今回の曖昧さには、2つの印を追加しました。",[31,167,172],{"className":168,"code":170,"language":171,"meta":39},[169],"language-go","type GLRLabel struct {\n\t\u002F\u002F Declaration 使用，规约出 Declaration 后消除\n\tTypeDef      bool     \u002F\u002F 是否是 TypeDef\n\tDeclaratorID []*Token \u002F\u002F 包含的 Identifier\n}\n","go",[19,173,170],{"__ignoreMap":39},[15,175,176,177,180],{},"typedefは、この宣言が型定義かを示します。最終的にdeclarationへ還元したときに印がなければ、普通の変数宣言です。DeclaratorIDはそのdeclarationが定義するシンボルで、型定義ならユーザー定義型の名前が入ります。function_definitionでも関数名をdeclarationと同じようなdeclaratorで扱うため（",[19,178,179],{"code":179},"function_definition := declaration_specifiers declarator compound_statement","）、DeclaratorIDには関数名も入ります。",[15,182,183],{},"この2つはAST構築中、下位ノードから上位ノードへ伝えます。",[31,185,188],{"className":186,"code":187,"language":171,"meta":39},[169],"gslice.ForEach(children, func(child *AstNode) {\n    if child.TypeDef {\n        parent.TypeDef = true\n    }\n    parent.DeclaratorID = append(parent.DeclaratorID, child.DeclaratorID...)\n})\n",[19,189,187],{"__ignoreMap":39},[15,191,192],{},"では、どこで設定するのでしょうか。",[15,194,195,196,199,200,203],{},"typedefは明確です。",[19,197,198],{"code":198},"storage_class_specifier := TYPEDEF","で還元するとき、そのノードの",[19,201,202],{"code":202},"typedef","をtrueにします。",[15,205,206,207,210,211,214],{},"DeclaratorIDは少し複雑です。基本は",[19,208,209],{"code":209},"direct_declarator := IDENTIFIER","です。列挙定数も考慮し、",[19,212,213],{"code":213},"enumeration_constant := IDENTIFIER","も処理します。",[15,216,217],{},"ただし、この2つを無制限に上へ伝えてはいけません。構築後にトップダウンでノードを処理するときは、その階層の情報だけを扱いたく、下位の情報が混ざっていては困ります。Cのスコープでは上位の情報は下位へ伝わりますが、下位の情報は上位に影響しません。そこで特定のノードへの還元時に印を消し、上への伝播を止めます。",[15,219,220,223,224,227,228,231,232,235,236,238,239,242],{},[19,221,222],{"code":222},"declaration","と",[19,225,226],{"code":226},"function_definition","への還元時に加え、",[19,229,230],{"code":230},"direct_declarator","の還元にも注意が必要です。",[19,233,234],{"code":234},"direct_declarator := direct_declarator LEFT_PARENTHESES parameter_type_list RIGHT_PARENTHESES","のような規則では、右辺の",[19,237,230],{"code":230},"にあるDeclaratorIDだけを引き継ぎます。これで",[19,240,241],{"code":241},"parameter_type_list","の引数宣言が混ざるのを防げます。",[15,244,245],{},"AST構築中に確実に行える検査は、次の2つです。",[65,247,248,251],{},[68,249,250],{},"ユーザー定義型の使用時に、以前に宣言された型か確認する。変数宣言による隠蔽はまだ確認できない。",[68,252,253,256,257,260,261,263],{},[19,254,255],{"code":255},"declaration_specifiers","にユーザー定義型の",[19,258,259],{"code":259},"type_specifier","が含まれるなら、",[19,262,259],{"code":259},"はそれ1つだけにする。ユーザー定義型はすでに完全な型なので、他の型指定子とは組み合わせない。",[15,265,266,267,270,271,274,275,277,278,280],{},"1つ目は、構築中にユーザー定義型のスコープスタックを維持します。",[19,268,269],{"code":269},"{","のシフトで新しいスコープを積み、",[19,272,273],{"code":273},"}","のシフトでスタック先頭のスコープを取り除きます。Declarationへ還元したらtypedefの印を確認し、型定義ならそのノードの全DeclaratorIDをスタック先頭のスコープへ追加します。",[19,276,88],{"code":88},"で還元したノードでは、",[19,279,82],{"code":82},"が以前に定義された型であるはずなので、スタックの上から下へ探します。",[15,282,283,284,286,287,286,289,292,293,295],{},"2つ目は簡単で、",[19,285,222],{"code":222},"、",[19,288,226],{"code":226},[19,290,291],{"code":291},"parameter_declaration","への還元時に",[19,294,255],{"code":255},"を検査すればよいだけです。",[11,297,299],{"id":298},"ast構築後","AST構築後",[15,301,302],{},"上記の構築中の検査は型名だけを扱い、変数名を見ていません。そのため、次のような誤りや曖昧さは残ります。",[31,304,307],{"className":305,"code":306,"language":103,"meta":39},[101],"typedef int a;\nint main() {\n\tint a;\n\ta c;\t\u002F\u002F 类型 a 已经被变量 a 遮蔽，此处声明不合法\n}\n",[19,308,306],{"__ignoreMap":39},[15,310,311],{},"そこで構築後は、スコープごとに型名と変数名の両方を記録する、もう少し詳しいシンボルテーブルを使います。",[31,313,316],{"className":314,"code":315,"language":171,"meta":39},[169],"type ScopeSymbols struct {\n\tTypeNames map[string]*entity.Token\n\tVarNames  map[string]*entity.Token\n}\n",[19,317,315],{"__ignoreMap":39},[15,319,320,321,323,324,326,327,329],{},"構築中と同様、",[19,322,269],{"code":269},"でスコープを積み、",[19,325,273],{"code":273},"でスタック先頭のスコープを取り除きます。",[19,328,222],{"code":222},"ノードにtypedefの印があればDeclaratorIDをスタック先頭のスコープの型名に、なければ変数名に追加します。変数名の追加時は、同じスコープに同名の型名がないかを調べ、あればエラーにします。型名を追加するときも逆の検査をします。",[15,331,332,333,336,337,340],{},"関数定義の関数名も、変数シンボルとしてテーブルに追加します。関数定義は",[19,334,335],{"code":335},"function_definition := declaration_specifiers declarator...","という形で、",[19,338,339],{"code":339},"declarator","のDeclaratorIDが関数名です。",[15,342,343,344,346,347,349],{},"続いて、型名と変数名の使用箇所を検査します。ユーザー定義型の使用箇所は",[19,345,88],{"code":88},"だけで、型が定義済みかは構築中に確認済みです。構築後には、さらに内側のスコープの変数名で隠されていないかを調べ、隠されていればエラーにします。変数名は",[19,348,78],{"code":78},"に現れ、同じように検査します。",[15,351,352],{},"変数名を検査する簡単な例です。",[31,354,357],{"className":355,"code":356,"language":171,"meta":39},[169],"func (s *symbolStack) CheckVar(token *entity.Token, depth int) error {\n\tfor i := depth; i >= 0; i-- {\n\t\tif previous, ok := s.stack[i].TypeNames[token.Lexeme]; ok {\n\t\t\treturn InvalidSymbolKind(token.SourceStart, previous.SourceStart, token.Lexeme)\n\t\t}\n\t\tif _, ok := s.stack[i].VarNames[token.Lexeme]; ok {\n\t\t\treturn nil\n\t\t}\n\t}\n\treturn UndeclaredIdentifier(token.SourceStart, token.Lexeme)\n}\n",[19,358,356],{"__ignoreMap":39},[15,360,361],{},"関数定義とforループでは、スコープを特別扱いします。関数引数やforの条件部分、つまり括弧の中身は、関数やループが置かれたスコープではなく、その内側の関数本体・ループ本体のスコープに属します。forループを例にすると、次のようになります。",[31,363,366],{"className":364,"code":365,"language":171,"meta":39},[169],"currentSymbolStackDepth := s.symbolStack.currentSymbolStackDepth\ns.symbolStack.SwitchScope(currentSymbolStackDepth + 1)\t\u002F\u002F 切换到深层作用域\nfor i := 0; i \u003C len(node.Children)-1; i++ {\n\tif err := s.Chop(node.Children[i]); err != nil {\n\t\treturn err\n\t}\n}\ns.symbolStack.SwitchScope(currentSymbolStackDepth)\t\t\u002F\u002F 切换回当前作用域\nif err := s.Chop(node.Children[len(node.Children)-1]); err != nil {\n\t\u002F\u002F 如果循环体中包含 {，则会自然进入\n\treturn err\n}\ns.symbolStack.EnterScope(currentSymbolStackDepth)\t\t\u002F\u002F 若不存在循环体，则会导致深层作用域无法弹出，这里强行重置一下\n",[19,367,365],{"__ignoreMap":39},{"title":39,"searchDepth":369,"depth":369,"links":370},4,[371,373,374,375],{"id":13,"depth":372,"text":13},3,{"id":57,"depth":372,"text":57},{"id":161,"depth":372,"text":162},{"id":298,"depth":372,"text":299},[377],"fiddling","2025-03-15 20:35:00","構文解析では、ユーザー定義型名と通常の変数名を見分けることが課題になります。たとえば`a*b;`は算術式とも宣言とも解釈できます。とくに型指定子に関する文法規則によって変数名が型名と解釈され、正確さや読みやすさに影響します。初期化を伴わない変数宣言は多いため、この曖昧さはソースコードの随所に現れます。",false,"md","https:\u002F\u002Fblog-img.774352199.xyz\u002F2VKHK9.webp",{"slots":384},{},true,"\u002Ffiddling\u002Fparser-type-variable-ambiguity",null,{"text":389,"minutes":390,"time":391,"words":392},"14 min read",13.58,814800,2716,{"title":5,"description":379},"Cのa*bが式と宣言の両方に読める曖昧さを、GLR解析の前後で処理。簡易シンボル表、型の印、変数による隠蔽とスコープの検査で、誤ったASTを除外する方法を説明します。",{"loc":386},"posts\u002Ffiddling\u002Fparser-type-variable-ambiguity",[398,399,400,401,402],"構文解析","GLR","シンボルテーブル","スコープ","曖昧性解消","tech","glaws9tolhoV8UziZP0vQQB9npvPB4kRTheI84sj6tk",[406,424,441,459,476,494,512,530,548,564,580,596,612,628,645,663,678,695,709,726,744,761,776,780,796,815,832,849,867,881,899,917,933,948,962,979,994,1009,1024,1038,1052,1066,1081,1095,1109],{"categories":407,"date":409,"description":410,"image":411,"path":412,"readingTime":413,"recommend":387,"tags":418,"title":423,"type":403},[408],"daily","2024-09-01 22:03:10","子どもの頃からの胃腸の不調が大学時代には不思議と消えたものの、就職後の夜更かしと飲酒で再発。慢性胃炎との付き合いは一筋縄ではいきませんでした。吐き気や胃のむかつきが日常になり、何度か検査を受けて生活を振り返るうちに、ようやく腰を据えて治療に向き合うようになりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002F0Hr9l5.webp","\u002Fdaily\u002Fanti-chronic-gastritis",{"text":414,"minutes":415,"time":416,"words":417},"7 min read",6.485,389100,1297,[419,420,421,422],"慢性胃炎","受診記録","胃内視鏡検査","健康記録","慢性胃炎の治療記録",{"categories":425,"date":426,"description":427,"image":428,"path":429,"readingTime":430,"recommend":387,"tags":435,"title":440,"type":403},[408],"2022-04-11 00:13:13","『三体』では、劉慈欣が壮大な歴史を通して個人と集団の関係を描いています。西側の民主主義への疑念と、大多数の人々に運命を委ねることへの悲観が、三部作を貫いています。英雄たちが力を尽くしても、その努力は歴史の流れに押し流される。文化大革命から始まる物語に、少数の傑出した人物と平凡な大衆の対立を読み、人間性と社会について考えました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FLTzbFP.webp","\u002Fdaily\u002Fpeople-in-three-body",{"text":431,"minutes":432,"time":433,"words":434},"19 min read",18.495,1109700,3699,[436,437,438,439],"三体","劉慈欣","SF文学","読書ノート","『三体』における「大多数の人々」",{"categories":442,"date":443,"description":444,"image":445,"path":446,"readingTime":447,"recommend":387,"tags":452,"title":458,"type":403},[408],"2024-01-04 02:06:51","2024年の学習目標は、日本語をN2レベルに引き上げること、SICPとTAPLを最後までやり切ること、POSIXを完全に実装したカーネルを作ること、そしてブログのテーマを更新すること。どれも簡単ではありませんが、今年取り組む方向は決まりました。","https:\u002F\u002Fblog-img.774352199.xyz\u002FV3rSQC.webp","\u002Fdaily\u002Fplan2024",{"text":448,"minutes":449,"time":450,"words":451},"1 min read",0.345,20700,69,[453,454,455,456,457],"年間計画","日本語学習","SICP","TAPL","オペレーティングシステム","2024年の学習計画",{"categories":460,"date":461,"description":462,"image":463,"path":464,"readingTime":465,"recommend":387,"tags":470,"title":475,"type":403},[408],"2024-09-28 16:26:00","ByteDanceで働いて3年。変化の速い環境で、時間まで加速したように感じながらも、どうにか心のバランスを保ってきました。杭州のオフィスのベランダから遠くの山を眺めていた入社当初を振り返り、仕事の壁や心境の変化、忙しさの中で自分のペースを探してきた日々を記します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhnCaht.webp","\u002Fdaily\u002Fwork-for-3-years",{"text":466,"minutes":467,"time":468,"words":469},"20 min read",19.73,1183800,3946,[471,472,473,474],"ByteDance","エンジニアのキャリア","仕事の振り返り","メンタルヘルス","ByteDanceで3年働きながら、ある程度の正気を保つことも不可能ではない",{"categories":477,"date":478,"description":479,"image":480,"path":481,"readingTime":482,"recommend":387,"tags":487,"title":493,"type":403},[377],"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":483,"minutes":484,"time":485,"words":486},"4 min read",3.455,207300,691,[488,489,490,491,492],"Astro","Google Analytics","Google Tag Manager","Partytown","アクセス解析","AstroにGoogle Analyticsを導入する（Tag Manager編）",{"categories":495,"date":496,"description":497,"image":498,"path":499,"readingTime":500,"recommend":505,"tags":506,"title":511,"type":403},[377],"2023-04-08 13:16:36","新しいプログラミング言語の設計は、難しくも面白い作業です。複雑なコンパイラ理論や機能の実装詳細をいったん脇に置き、コードがコンピューターのどこで動くかに注目すると、言語の作り方が見えてきます。RISC-VI命令セットを出発点に、基盤となる構造、階層化されたシステム、仮想マシンのモデルをたどり、言語の本質を考えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FuO420B.webp","\u002Ffiddling\u002Fchitchat-about-programming-language",{"text":501,"minutes":502,"time":503,"words":504},"28 min read",27.03,1621800,5406,2,[507,508,509,510],"プログラミング言語設計","型システム","コンパイラ設計","RISC-V","プログラミング言語についての雑談",{"categories":513,"date":514,"description":515,"image":516,"path":517,"readingTime":518,"recommend":369,"tags":523,"title":529,"type":403},[377],"2025-04-18 16:43:12","彼女が仕事で北京から上海に引っ越したので、回線の手配も手伝いました。ところが上海電信の500Mは杭州の1000Mより高く、なんとも納得がいきません。そこで上海での透過プロキシ、特定の通信の杭州経由での外部接続、両拠点のLAN相互接続を目指してネットワークを組むことにしました。杭州側はソフトウェアルーターと無線APのシンプルな構成で、普段から自宅経由で通信できる環境があり、次の挑戦に向けた準備はできています。","https:\u002F\u002Fblog-img.774352199.xyz\u002FO6cAGh.webp","\u002Ffiddling\u002Fcross-city-network-setup",{"text":519,"minutes":520,"time":521,"words":522},"11 min read",10.14,608400,2028,[524,525,526,527,528],"Tailscale","mihomo","拠点間ネットワーク","透過プロキシ","ホームネットワーク","上海と杭州の自宅ネットワークをつなぐ",{"categories":531,"date":532,"description":533,"image":534,"path":535,"readingTime":536,"recommend":387,"tags":541,"title":547,"type":403},[377],"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":537,"minutes":538,"time":539,"words":540},"10 min read",9.585,575100,1917,[542,543,544,545,546],"CSAPP","WSL2","Linux","GDB","実験環境","CSAPP Labの環境構築",{"categories":549,"date":550,"description":551,"image":552,"path":553,"readingTime":554,"recommend":387,"tags":559,"title":563,"type":403},[377],"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":555,"minutes":556,"time":557,"words":558},"18 min read",17.525,1051500,3505,[560,561,525,562,527],"Debian","サイドルーター","AdGuard Home","Debianをサイドルーターにする",{"categories":565,"date":566,"description":567,"image":568,"path":569,"readingTime":570,"recommend":387,"tags":574,"title":579,"type":403},[377],"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":389,"minutes":571,"time":572,"words":573},13.1,786000,2620,[575,576,527,577,578],"FakeIP","sing-box","ポリシーベースルーティング","トラフィック振り分け","FakeIPを使った透過プロキシの振り分け",{"categories":581,"date":582,"description":583,"image":584,"path":585,"readingTime":586,"recommend":387,"tags":591,"title":595,"type":403},[377],"2024-08-15 23:50:00","サイドルーターを導入すると、メインルーターのポート転送が効かなくなることがあります。ゲートウェイをサイドルーターに変えることで通信経路が変わり、メインルーターを前提とした転送が正常に動かなくなるためです。ゲートウェイはアドレスを変換して内部ネットワークの通信を外部へ転送し、各端末は外部との通信にこれを必要とします。この仕組みを理解すると、ポート転送の問題を解決しやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FmRqws9.webp","\u002Ffiddling\u002Ffix-port-forward-in-bypass-router",{"text":587,"minutes":588,"time":589,"words":590},"6 min read",5.155,309300,1031,[561,592,593,594],"ポート転送","NAT","ネットワークのトラブルシューティング","サイドルーター環境でポート転送が効かない問題を解決する",{"categories":597,"date":598,"description":599,"image":600,"path":601,"readingTime":602,"recommend":387,"tags":607,"title":611,"type":403},[377],"2023-02-02 23:24:55","春節の帰省列車で、Goをベアメタルで動かす記事を読み、低レベルのシステムインターフェースに興味が湧きました。実際に動く実装を見て、高級言語でOSを作る可能性に胸が躍ります。関連研究を調べると先行例も見つかり、積もった熱意は期待に満ちたプロジェクトへと変わりました。しかし、最後は思いどおりにはいきませんでした。","https:\u002F\u002Fblog-img.774352199.xyz\u002FxB1Ni5.webp","\u002Ffiddling\u002Fgo-os",{"text":603,"minutes":604,"time":605,"words":606},"12 min read",11.81,708600,2362,[608,510,457,609,610],"Go","ベアメタルプログラミング","ランタイム","失敗に終わったプロジェクト：楽しくなかった春節の7日間",{"categories":613,"date":614,"description":615,"image":616,"path":617,"readingTime":618,"recommend":387,"tags":623,"title":627,"type":403},[377],"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":619,"minutes":620,"time":621,"words":622},"5 min read",4.14,248400,828,[608,624,625,626],"リフレクション","ディープコピー","構造体変換","Goで異なる型の構造体をディープコピーする",{"categories":629,"date":630,"description":631,"image":632,"path":633,"readingTime":634,"recommend":387,"tags":638,"title":644,"type":403},[377],"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":483,"minutes":635,"time":636,"words":637},3.76,225600,752,[639,640,641,642,643],"Apple Watch","Health Auto Export","InfluxDB","Grafana","心拍数モニタリング","My Heart Beats for U：心拍数をGrafanaで可視化する",{"categories":646,"date":647,"description":648,"image":649,"path":650,"readingTime":651,"recommend":655,"tags":656,"title":662,"type":403},[377],"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":414,"minutes":652,"time":653,"words":654},6.94,416400,1388,5,[657,658,659,660,661],"macOS 26","iPadOS 26","Liquid Glass","Apple Intelligence","OS使用感","macOS 26とiPadOS 26を試してみた",{"categories":664,"date":665,"description":666,"image":667,"path":668,"readingTime":669,"recommend":387,"tags":673,"title":677,"type":403},[377],"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":537,"minutes":670,"time":671,"words":672},9.74,584400,1948,[674,660,675,676],"macOS 27","ChatGPT","中国本土向けMac","中国本土向けMacでApple Intelligenceを使う：地域変更からChatGPTの取り出しまで",{"categories":679,"date":680,"description":681,"image":682,"path":683,"readingTime":684,"recommend":387,"tags":688,"title":694,"type":403},[377],"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":519,"minutes":685,"time":686,"words":687},10.98,658800,2196,[689,690,691,692,693],"MoonTV","LunaTV","Vibe Coding","Cursor","AI支援開発","MoonTV：Vibe Codingを試してみた",{"categories":696,"date":697,"description":698,"image":699,"path":700,"readingTime":701,"recommend":387,"tags":705,"title":708,"type":403},[377],"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":587,"minutes":702,"time":703,"words":704},5.75,345000,1150,[706,707,577,578],"BGP","IPアドレスデータベース","BGPで中国国内・国外IPの振り分けをより正確にする",{"categories":710,"date":711,"description":712,"image":713,"path":714,"readingTime":715,"recommend":387,"tags":720,"title":725,"type":403},[377],"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":716,"minutes":717,"time":718,"words":719},"9 min read",8.96,537600,1792,[721,722,723,724],"Microsoft Flight Simulator 2024","Thrustmaster TCA","PICO VR","フライトシミュレーション","Microsoft Flight Simulator 2024をあれこれ試す",{"categories":727,"date":728,"description":729,"image":730,"path":731,"readingTime":732,"recommend":387,"tags":737,"title":743,"type":403},[377],"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":733,"minutes":734,"time":735,"words":736},"15 min read",14.05,843000,2810,[738,739,740,741,742],"Android","OPPO","iOS","スマートフォン使用感","エコシステム移行","Androidに乗り換えて1か月",{"categories":745,"date":746,"description":747,"image":748,"path":749,"readingTime":750,"recommend":387,"tags":754,"title":760,"type":403},[377],"2026-05-11 22:43:00","GitHub Trendingで旅行計画ツールを見つけ、自分でも動かしたくなりました。どうせ新しいVPSを借りるなら、ついでにもう少し、いや、だいぶ色々入れてしまおうと。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBBdDWW.webp","\u002Ffiddling\u002Fone-trek-twenty-stacks",{"text":519,"minutes":751,"time":752,"words":753},10.34,620400,2068,[755,756,757,758,759],"TREK","Docker Compose","Dockge","VPS","セルフホスティング","TREKひとつのつもりが、20個のスタックに",{"categories":762,"date":763,"description":764,"image":765,"path":766,"readingTime":767,"recommend":387,"tags":771,"title":775,"type":403},[377],"2025-01-16 23:09:00","OPNsenseは、美しい画面と充実した機能を備えるオープンソースのファイアウォール・ルーターです。いくつかの構成を試した末に、透過プロキシやトラフィック振り分けでの可能性に気づきました。BGPベースの振り分けと組み合わせることで安全性と安定性を高められ、IPリストの自動更新で管理もしやすくなります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FxA8C1E.webp","\u002Ffiddling\u002Fopnsense-transparent-proxy",{"text":603,"minutes":768,"time":769,"words":770},11.38,682800,2276,[772,773,525,774,527,578],"OPNsense","FreeBSD","tun2socks","OPNsenseで透過プロキシとトラフィック振り分けを実現する",{"categories":777,"date":378,"description":379,"image":382,"path":386,"readingTime":778,"recommend":372,"tags":779,"title":5,"type":403},[377],{"text":389,"minutes":390,"time":391,"words":392},[398,399,400,401,402],{"categories":781,"date":782,"description":783,"image":784,"path":785,"readingTime":786,"recommend":387,"tags":790,"title":795,"type":403},[377],"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":483,"minutes":787,"time":788,"words":789},3.89,233400,778,[510,791,792,793,794],"Spike","riscv-pk","クロスコンパイル","ツールチェーン","RISC-Vツールチェーンとエミュレーターのインストール",{"categories":797,"date":798,"description":799,"image":800,"path":801,"readingTime":802,"recommend":806,"tags":807,"title":814,"type":403},[377],"2026-09-09 23:59:00","これも一種のNTRですよね","https:\u002F\u002Fblog-img.774352199.xyz\u002FNDPUwc.webp","\u002Ffiddling\u002Fsteamdeck-switch-60fps",{"text":389,"minutes":803,"time":804,"words":805},13.905,834300,2781,7,[808,809,810,811,812,813],"Steam Deck","Nintendo Switch","EmuDeck","Eden","Lossless Scaling","フレーム生成","Steam Deckの第二の人生：Switchエミュレーター導入からフレーム補間で60FPSまで",{"categories":816,"date":817,"description":818,"image":819,"path":820,"readingTime":821,"recommend":387,"tags":826,"title":831,"type":403},[377],"2024-06-23 15:31:32","GFWは単に出口のゲートウェイを監視するのではなく、通信経路の脇から国際通信を傍受します。出入国するIPパケットをクラスタへ複製し、詳しく分析・フィルタリングする仕組みです。どこで何をしているかを理解することは、検閲回避の検討に欠かせません。ネットワーク構成を調べることで、遮断の経路や技術、対処方法が見えてきます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FsOpJuL.webp","\u002Ffiddling\u002Ftech-about-gfw",{"text":822,"minutes":823,"time":824,"words":825},"25 min read",24.975,1498500,4995,[827,828,829,830],"GFW","DNSポイズニング","TCP","インターネット検閲","GFWの仕組みを探る",{"categories":833,"date":834,"description":835,"image":836,"path":837,"readingTime":838,"recommend":387,"tags":842,"title":848,"type":403},[377],"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":483,"minutes":839,"time":840,"words":841},3.88,232800,776,[843,844,845,846,847],"Java","javac","文字列連結","定数伝播","バイトコード","Javaのthisキーワードでコンパイル時の定数伝播が効かなくなる問題",{"categories":850,"date":851,"description":852,"image":853,"path":854,"readingTime":855,"recommend":387,"tags":860,"title":866,"type":403},[377],"2025-01-29 21:58:00","ひとこと投稿機能があれば、静的ブログの記事公開に伴う手間や心理的な負担を減らし、短い思いつきをいつでも共有できます。Cloudflare Workersでバックエンドを実装し、KVで投稿を保存・管理します。フロントエンドはVitePressにVueコンポーネントを埋め込み、投稿を手軽に表示してブログに動きと交流の場を加えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FhZX6hr.webp","\u002Ffiddling\u002Fvitepress-memos-component",{"text":856,"minutes":857,"time":858,"words":859},"24 min read",23.345,1400700,4669,[861,862,863,864,865],"VitePress","Vue","Cloudflare Workers","Cloudflare KV","マイクロブログ","VitePressにひとこと投稿機能を実装する",{"categories":868,"date":869,"description":870,"image":871,"path":872,"readingTime":873,"recommend":387,"tags":877,"title":880,"type":403},[377],"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":619,"minutes":874,"time":875,"words":876},4.09,245400,818,[878,879,758,577,578],"Cloudflare WARP","IPv6","VPSの特定の通信をWARP経由のIPv6で外に出す",{"categories":882,"date":883,"description":884,"image":885,"path":886,"readingTime":887,"recommend":891,"tags":892,"title":898,"type":403},[377],"2026-08-17 23:59:21","いじればいじるほど、もっといじりたくなります。年を取ってもまだまだ元気、まだまだ元気です。","https:\u002F\u002Fblog-img.774352199.xyz\u002FqfxB0h.webp","\u002Ffiddling\u002Fxiaomi17-root-and-hide-root",{"text":716,"minutes":888,"time":889,"words":890},8.83,529800,1766,6,[893,894,895,896,897],"Xiaomi 17","Bootloader","Android Root","ファームウェア書き換え","Rootの隠蔽","Xiaomi 17を普段使いに：ロック解除、ROM書き込み、root化とroot隠し",{"categories":900,"date":902,"description":903,"image":904,"path":905,"readingTime":906,"recommend":387,"tags":911,"title":916,"type":403},[901],"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":907,"minutes":908,"time":909,"words":910},"13 min read",12.39,743400,2478,[912,913,608,914,915],"MIT 6.5840","MapReduce","RPC","並行プログラミング","6.5840 Lab 1：MapReduce",{"categories":918,"date":919,"description":920,"image":921,"path":922,"readingTime":923,"recommend":387,"tags":927,"title":932,"type":403},[901],"2022-01-16 17:32:00","MapReduceは、大規模なデータセットの処理を簡単にするための効率的な並列計算モデルです。利用者はMapとReduceという2つの主要な関数を定義することで、複雑なタスクを簡単な操作に分解できます。データの分配やタスクの割り当てはフレームワークが自動で管理するため、開発者は低レベルの細部に気を取られず、アルゴリズムそのものに集中できます。分散システムで広く使われていることからも、その柔軟性と実用性が分かります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FApIDdC.webp","\u002Fnotes\u002F65840\u002Fmapreducepaper",{"text":716,"minutes":924,"time":925,"words":926},8.085,485100,1617,[913,928,929,930,931],"分散システム","論文ノート","並列計算","耐障害性","MapReduce論文を読む",{"categories":934,"date":935,"description":936,"image":937,"path":938,"readingTime":939,"recommend":387,"tags":943,"title":947,"type":403},[901],"2022-12-16 02:06:10","Lab 2Aでは、Raftのリーダー選出とハートビートを実装し、さまざまな厳しい条件でも任期の交代や選挙が正常に行われるようにします。実習全体は4段階からなり、この後に実装する分散KVストアの土台になります。明示的なロックを使わない設計によって、Raft構造体を簡潔にします。実習の手引きには必要な背景知識が載っていますが、前の実習と比べると参考資料に頼れる部分はほとんどなく、自力で実装することが重視されます。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fc11Uk4.webp","\u002Fnotes\u002F65840\u002Fraftlab2a",{"text":555,"minutes":940,"time":941,"words":942},17.515,1050900,3503,[912,944,608,945,946],"Raft","リーダー選出","分散合意","6.5840 Lab 2A：リーダー選出",{"categories":949,"date":950,"description":951,"image":952,"path":953,"readingTime":954,"recommend":387,"tags":959,"title":961,"type":403},[901],"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":955,"minutes":956,"time":957,"words":958},"30 min read",29.245,1754700,5849,[944,946,960,929],"ログ複製","Raft論文を読む",{"categories":963,"date":965,"description":966,"image":967,"path":968,"readingTime":969,"recommend":973,"tags":974,"title":978,"type":403},[964],"projects","2021-11-27 14:43:00","MYDBは、データベースの基本原理を学び、実装してみるための個人プロジェクトです。空き時間を使い、半月あまりかけて作りました。大学のデータベースシステムの授業で基礎には触れたものの、インターン中は授業を口実にサボってばかりでした。面接で正直に答えても大きな問題にはなりませんでしたが、それをきっかけに自分の知識を見直し、実際に手を動かして学ぼうと考えるようになりました。そうして生まれたのがこのプロジェクトです。","https:\u002F\u002Fblog-img.774352199.xyz\u002Fxfci2J.webp","\u002Fprojects\u002Fmydb\u002Fmydb0",{"text":716,"minutes":970,"time":971,"words":972},8.03,481800,1606,1,[975,843,976,977],"MYDB","データベース実装","データベースアーキテクチャ","MYDB 0. プロジェクト構成と、先に伝えておきたいこと",{"categories":980,"date":981,"description":982,"image":983,"path":984,"readingTime":985,"recommend":387,"tags":990,"title":993,"type":403},[964],"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":986,"minutes":987,"time":988,"words":989},"8 min read",7.42,445200,1484,[975,843,991,992],"トランザクション管理","XID","MYDB 1. まずはシンプルなTMから",{"categories":995,"date":996,"description":997,"image":998,"path":999,"readingTime":1000,"recommend":387,"tags":1004,"title":1008,"type":403},[964],"2021-12-25 18:26:00","MYDBはMySQLに似たC\u002FS構成を採用し、複数のクライアントがソケットでサーバーへ接続してSQLを実行し、結果を受け取れます。通信には専用のバイナリー形式を使いますが、実装を簡単にするならプレーンテキストも選択肢です。サーバーとクライアントの基本的な転送構造によって、データのやり取りと処理を行います。","https:\u002F\u002Fblog-img.774352199.xyz\u002FPAHrUZ.webp","\u002Fprojects\u002Fmydb\u002Fmydb10",{"text":587,"minutes":1001,"time":1002,"words":1003},5.76,345600,1152,[975,843,1005,1006,1007],"Socket","クライアントサーバー構成","通信プロトコル","MYDB 10. サーバー・クライアントの実装と通信プロトコル",{"categories":1010,"date":1011,"description":1012,"image":1013,"path":1014,"readingTime":1015,"recommend":387,"tags":1019,"title":1023,"type":403},[964],"2021-11-30 23:18:00","データマネージャー（DM）は上位モジュールとファイルシステムをつなぎ、ページとキャッシュを管理しながら、データの安全性と復旧を支えます。キャッシュには従来のLRUではなく参照カウント方式を採用し、汎用性と効率を高めて、この先のデータ操作の土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FWdIGoG.webp","\u002Fprojects\u002Fmydb\u002Fmydb2",{"text":519,"minutes":1016,"time":1017,"words":1018},10.395,623700,2079,[975,843,1020,1021,1022],"参照カウント","キャッシュ設計","共有メモリ","MYDB 2. 参照カウント方式のキャッシュ基盤と共有バイト配列",{"categories":1025,"date":1026,"description":1027,"image":1028,"path":1029,"readingTime":1030,"recommend":387,"tags":1034,"title":1037,"type":403},[964],"2021-12-05 15:28:00","DMはファイルシステムをページとして抽象化し、ページ単位で読み書きとキャッシュを行います。データページのデフォルトサイズは8Kで、大量の書き込みではサイズの調整によって性能を高められます。実装済みの汎用キャッシュ基盤を使い、ここではページ構造を具体的に定義して、効率よくページを管理します。","https:\u002F\u002Fblog-img.774352199.xyz\u002FjlFC4E.webp","\u002Fprojects\u002Fmydb\u002Fmydb3",{"text":986,"minutes":1031,"time":1032,"words":1033},7.14,428400,1428,[975,843,1035,1036],"データページ","キャッシュ管理","MYDB 3. データページのキャッシュと管理",{"categories":1039,"date":1040,"description":1041,"image":1042,"path":1043,"readingTime":1044,"recommend":387,"tags":1048,"title":1051,"type":403},[964],"2021-12-08 22:55:00","MYDBでは、クラッシュ後にデータを復旧できるよう、ログファイルが重要な役割を担います。DMは下位のデータを操作するたびにログを生成・記録し、連続したログ列を作ります。チェックサムと各操作の記録を含む所定のバイナリー形式で保存することで、再起動時にデータの状態を正確に再構築し、整合性と完全性を保ちます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FTRcbsj.webp","\u002Fprojects\u002Fmydb\u002Fmydb4",{"text":907,"minutes":1045,"time":1046,"words":1047},12.685,761100,2537,[975,843,1049,1050],"データベースログ","クラッシュリカバリ","MYDB 4. ログファイルと復旧戦略",{"categories":1053,"date":1054,"description":1055,"image":1056,"path":1057,"readingTime":1058,"recommend":387,"tags":1062,"title":1065,"type":403},[964],"2021-12-11 15:16:00","ページインデックスはDM層の重要な構成要素です。各ページの空き容量をキャッシュすることで挿入処理を効率化し、上位モジュールが長い探索をせずに適切なページを素早く見つけられるようにします。実装ではデータ項目（DataItem）の抽象化とも密接に連携し、データベースの効率的な動作を支えます。","https:\u002F\u002Fblog-img.774352199.xyz\u002F22PSG1.webp","\u002Fprojects\u002Fmydb\u002Fmydb5",{"text":537,"minutes":1059,"time":1060,"words":1061},9.86,591600,1972,[975,843,1063,1064],"ページインデックス","データ管理","MYDB 5. ページインデックスとDMの実装",{"categories":1067,"date":1068,"description":1069,"image":1070,"path":1071,"readingTime":1072,"recommend":387,"tags":1076,"title":1080,"type":403},[964],"2021-12-18 14:58:00","VMは二相ロックでスケジュールの直列化可能性を保証し、多版型同時実行制御（MVCC）を導入して読み取りと書き込みの相互ブロックを解消します。また、データベース操作の競合を定義し、特に更新と読み取りの関係を整理することで、トランザクションの分離レベルを理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002F8YzotA.webp","\u002Fprojects\u002Fmydb\u002Fmydb6",{"text":733,"minutes":1073,"time":1074,"words":1075},14.665,879900,2933,[975,843,1077,1078,1079],"MVCC","トランザクション分離","二相ロック","MYDB 6. レコードのバージョンとトランザクション分離",{"categories":1082,"date":1083,"description":1084,"image":1085,"path":1086,"readingTime":1087,"recommend":387,"tags":1091,"title":1094,"type":403},[964],"2021-12-23 21:20:00","VMでは、MVCCに伴うバージョンの飛び越しとデッドロックに対処する必要があります。MYDBはトランザクションに印を付けるだけで取り消しやロールバックを行い、abortedなトランザクションのデータがほかへ影響しないようにします。この設計により並行処理の効率と信頼性を高め、従来の2PLで起こりがちなデッドロックを避けて、システム全体の安定性と性能を向上させます。","https:\u002F\u002Fblog-img.774352199.xyz\u002FBF3yDW.webp","\u002Fprojects\u002Fmydb\u002Fmydb7",{"text":603,"minutes":1088,"time":1089,"words":1090},11.32,679200,2264,[975,843,1092,1093],"デッドロック検出","バージョン管理","MYDB 7. デッドロック検出とVMの実装",{"categories":1096,"date":1097,"description":1098,"image":1099,"path":1100,"readingTime":1101,"recommend":387,"tags":1105,"title":1108,"type":403},[964],"2021-12-24 21:01:00","MYDBはB+木によるクラスタ化インデックスを実装します。IMはバージョンマネージャー（VM）を経由せず、データマネージャー（DM）と直接やり取りし、インデックスデータをデータベースファイルへ直接書き込みます。この章では二分木インデックスの構造を詳しく説明し、葉フラグ、キー数、兄弟ノードの識別子など、インデックス検索の基盤となる要素を扱います。","https:\u002F\u002Fblog-img.774352199.xyz\u002Ff92X4o.webp","\u002Fprojects\u002Fmydb\u002Fmydb8",{"text":414,"minutes":1102,"time":1103,"words":1104},6.53,391800,1306,[975,843,1106,1107],"B+木","データベースインデックス","MYDB 8. インデックス管理",{"categories":1110,"date":1111,"description":1112,"image":1113,"path":1114,"readingTime":1115,"recommend":387,"tags":1119,"title":1122,"type":403},[964],"2021-12-25 15:44:00","テーブルマネージャー（TBM）は、フィールドとテーブルの構造を管理します。ParserはSQL風の文を構造化して解析し、文に含まれる情報を対応するクラスへまとめることで、その後の操作を簡単にします。この章ではMYDBのSQL構文も紹介し、管理処理全体を理解する土台を作ります。","https:\u002F\u002Fblog-img.774352199.xyz\u002FzOMyv5.webp","\u002Fprojects\u002Fmydb\u002Fmydb9",{"text":986,"minutes":1116,"time":1117,"words":1118},7.99,479400,1598,[975,843,1120,1121],"SQL解析","テーブル管理","MYDB 9. フィールドとテーブルの管理",1789914058482]