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