<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Flaneur2020</title><link>https://flaneur2020.github.io/</link><description>Recent content on Flaneur2020</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 24 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://flaneur2020.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>Notes on CRAQ</title><link>https://flaneur2020.github.io/posts/2026-05-24-craq/</link><pubDate>Sun, 24 May 2026 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2026-05-24-craq/</guid><description>Recently while studying 3fs, I learned that it uses CRAQ (Chain Replication with Apportioned Queries) as its replication algorithm. Coincidentally, I had similar requirements at work, so I&amp;rsquo;m documenting my understanding of CRAQ here.
CRAQ is already a quite popular engineering solution for replication in object storage or KV systems. CRAQ can be viewed as a simple enhancement to traditional chain replication. However, unlike consensus algorithms like Raft, CRAQ only focuses on data replication itself.</description></item><item><title>A Walkthrough of nano-vllm</title><link>https://flaneur2020.github.io/posts/2025-10-12-nano-vllm/</link><pubDate>Sun, 12 Oct 2025 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2025-10-12-nano-vllm/</guid><description>Recently, I&amp;rsquo;ve been delving into the architecture of production-grade inference engines. While projects like vLLM and SGLang are crazy sophisticated, their complexity can make detailed code tracing difficult. Over the holidays, I came across nano-vllm—a tightly scoped codebase that still delivers end-to-end support for Page Attention and scheduling. I took a deep dive into its internals and have compiled my technical notes here.
Code Structure nano-vllm features a clean, approachable layout.</description></item><item><title>Notes on RL: Policy Gradient &amp; Log Derivative Trick</title><link>https://flaneur2020.github.io/posts/2025-02-25-policy-gradient/</link><pubDate>Tue, 25 Feb 2025 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2025-02-25-policy-gradient/</guid><description>Recently I followed this tutorial to implement a basic Q-Learning reinforcement learning algorithm for Flappy Bird, which surprisingly worked quite well, reaching over 10,000 points.
Q-Learning essentially estimates a value $Q(s, a)$ for each state-action pair $(s, a)$, and then selects actions based on these $Q$ values. Deep Q-Network (DQN) builds on basic Q-Learning by adding a neural network to estimate $Q$ values, essentially compressing the Q Table using a neural network.</description></item><item><title>Notes on Diffusion Model: Intuition</title><link>https://flaneur2020.github.io/posts/2024-07-22-diffusion-model/</link><pubDate>Mon, 22 Jul 2024 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2024-07-22-diffusion-model/</guid><description>Diffusion Model is undoubtedly the SOTA in image generation right now. When looking for resources to learn about Diffusion Model, most articles I found were packed with heavy math, like ELBO derivations, which were too tough for me. This article tries to avoid those concepts and focuses solely on the intuition behind it.
Idea In VAE, image generation is seen as sampling from a Gaussian distribution. In Diffusion Model, image generation is seen as a series of gradual denoising processes.</description></item><item><title>Notes on Variational Autoencoder: Maths</title><link>https://flaneur2020.github.io/posts/2024-07-14-vae-maths/</link><pubDate>Sun, 14 Jul 2024 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2024-07-14-vae-maths/</guid><description>In the last blog, I went over the intuition behind VAE, which was pretty straightforward. However, when reading articles about the math behind VAE, I always felt something was missing. So, I spent two weeks (except for eating and sleeping) working through the math until I finally got the formulas down. The whole process was quite challenging for someone with my math background, so I&amp;rsquo;m documenting it here.
Prerequisites Before diving into the formulas, let&amp;rsquo;s review/preview the math we&amp;rsquo;ll be using.</description></item><item><title>Notes on Variational Autoencoder: Intuition</title><link>https://flaneur2020.github.io/posts/2024-06-09-notes-on-vae/</link><pubDate>Sun, 09 Jun 2024 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2024-06-09-notes-on-vae/</guid><description>Recently, I wanted to learn about Stable Diffusion, but it seemed like I needed to first understand what VAE (Variational Autoencoder) is all about. Here, I&amp;rsquo;ll jot down my naive understanding of VAE. I haven&amp;rsquo;t fully grasped the math behind ELBO yet, so I&amp;rsquo;ll note that separately later.
The article &amp;ldquo;Intuitively Understanding Variational Autoencoders&amp;rdquo; does a great job explaining the intuition behind VAE, so this is kind of a manual summary.</description></item><item><title>Spilled Hash Aggregation</title><link>https://flaneur2020.github.io/posts/2023-02-07-spilled-hash/</link><pubDate>Tue, 07 Feb 2023 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2023-02-07-spilled-hash/</guid><description>I didn&amp;rsquo;t pay much attention to Spilling before because an article about Presto mentioned that Facebook didn&amp;rsquo;t enable it in production. Given Facebook&amp;rsquo;s massive cluster size, memory can be considered infinite. The maintenance cost of adding extra disks to compute nodes might outweighs the benefits of Spilling.
However, recently I encountered some OOM cases. Without Facebook&amp;rsquo;s large-scale permanent cluster size, Spilling is still a good option. Especially for products like DuckDB, &amp;ldquo;Never OOM&amp;rdquo; is indeed a big selling point.</description></item><item><title>Snapshot in Postgres</title><link>https://flaneur2020.github.io/posts/2022-08-16-postgres-snapshot/</link><pubDate>Tue, 16 Aug 2022 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2022-08-16-postgres-snapshot/</guid><description>Recently, I wanted to learn about the postgres ecosystem. I didn&amp;rsquo;t quite get its MVCC mechanism before, so I&amp;rsquo;m trying to understand it again. For now, I&amp;rsquo;ll ignore the concurrency control and cleanup parts of MVCC and just focus on the Snapshot part.
Tuple Postgres doesn&amp;rsquo;t have MySQL&amp;rsquo;s UNDO log. Multi-version data (Tuples) are stored directly in the tablespace with version-related metadata. For now, let&amp;rsquo;s just look at the xmin and xmax fields:</description></item><item><title>ReplacingMergeTree and CollapsingMergeTree</title><link>https://flaneur2020.github.io/posts/2022-01-25-ck-replacing-merge-tree/</link><pubDate>Tue, 25 Jan 2022 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2022-01-25-ck-replacing-merge-tree/</guid><description>We learned earlier that data in ClickHouse doesn&amp;rsquo;t support updates, only insertions. If the same primary key has updates, it results in two rows in the table.
That&amp;rsquo;s where ReplacingMergeTree from the MergeTree family comes in. It can do some merging during compaction to clean up duplicate data, leaving only the latest data for the primary key.
Sounds good, right? But during contiguous data insertion, you can&amp;rsquo;t guarantee there won&amp;rsquo;t be duplicate primary keys.</description></item><item><title>MergeTree in ClickHouse: Compaction</title><link>https://flaneur2020.github.io/posts/2022-01-24-ck-merge-tree-compact/</link><pubDate>Mon, 24 Jan 2022 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2022-01-24-ck-merge-tree-compact/</guid><description>First off, I thought MergeTree was just like leveldb&amp;rsquo;s LSM, but after digging into ClickHouse&amp;rsquo;s MergeTree, I couldn&amp;rsquo;t find any of the familiar stuff, and I was confused for a while.
First, leveldb&amp;rsquo;s LSM has WAL + MemTable + SSTable. When reading data, each level has an iterator that forms a MergeIterator, reflecting the latest updates. Running compaction mainly cleans up old data and keeps the new data, mainly serving updates: on the basis of immutable files, it implements mutable KV semantics.</description></item><item><title>Two-Phase Commit in CRDB</title><link>https://flaneur2020.github.io/posts/2021-09-06-crdb-txn/</link><pubDate>Mon, 06 Sep 2021 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2021-09-06-crdb-txn/</guid><description>My impression about Percolator was that it could enable transactional capabilities on a regular distributed KV store, but the overhead of the 2PC + Raft process was significant. A few days ago, I heard that CockroachDB (CRDB) has made some engineering optimizations compared to Percolator. I decided to learn about these implementation ideas.
Similar to Percolator, CRDB also implements decentralized transaction management for multi-row transactions. The challenge lies in the potential concurrency conflicts for each row operation.</description></item><item><title>Transaction Internals: RocksDB</title><link>https://flaneur2020.github.io/posts/2021-08-14-rocksdb-txn/</link><pubDate>Sat, 14 Aug 2021 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2021-08-14-rocksdb-txn/</guid><description>RocksDB supports two concurrency control modes: PessimisticTransactionDB and OptimisticTransactionDB. Both seem to be external wrappers around the DB object, implementing concurrency control outside of storage. This allows applications to perform transactional KV read and write operations through BEGIN, COMMIT, and ROLLBACK APIs.
RocksDB inherently supports atomic write capabilities with WriteBatch. Transactions build on WriteBatch, with writes within a transaction temporarily stored in its own WriteBatch. During reads, it first reads from its WriteBatch, then from MemTable, L0, L1, etc.</description></item><item><title>Transaction Internals: Badger</title><link>https://flaneur2020.github.io/posts/2021-08-01-badger-txn/</link><pubDate>Sun, 01 Aug 2021 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2021-08-01-badger-txn/</guid><description>Badger is an open-source LSM Tree KV engine developed by dgraph. Compared to leveldb, it introduced various improvements such as KV separation, transactions, and concurrent compactions, making it a more production-ready storage engine in the Go ecosystem. Let&amp;rsquo;s take a look at its transaction implementation.
Badger implements optimistic concurrency control (OCC) transactions with Serializable Snapshot Isolation (SSI) level. Compared to Snapshot Isolation (SI), SSI not only tracks write operations for conflict detection but also tracks read operations within transactions.</description></item><item><title>Notes on LevelDB: Writes</title><link>https://flaneur2020.github.io/posts/2021-04-11-leveldb-writes/</link><pubDate>Sun, 11 Apr 2021 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2021-04-11-leveldb-writes/</guid><description>All write operations in LevelDB, including Put and Delete are unified and recorded in the WriteBatch structure, then passed through the Write function as the only entry point for write operations:
Status DB::Put(const WriteOptions&amp;amp; opt, const Slice&amp;amp; key, const Slice&amp;amp; value) { WriteBatch batch; batch.Put(key, value); return Write(opt, &amp;amp;batch); } Status DB::Delete(const WriteOptions&amp;amp; opt, const Slice&amp;amp; key) { WriteBatch batch; batch.Delete(key); return Write(opt, &amp;amp;batch); } The Write function takes a WriteOptions and WriteBatch as parameters:</description></item><item><title>Notes on ZGC: Colored Pointers</title><link>https://flaneur2020.github.io/posts/2020-08-26-notes-zgc/</link><pubDate>Wed, 26 Aug 2020 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2020-08-26-notes-zgc/</guid><description>ZGC is a new garbage collector introduced in jdk11, promising pause times of no more than 10ms, and these pauses are independent of heap size, supporting heaps up to terabytes.
As a fan of Go, you might think Go&amp;rsquo;s GC is already pretty good, right? It only has a little STW during Initial Mark, and regular GC pauses are usually under a millisecond? In reality, Go&amp;rsquo;s GC is still far from ZGC&amp;rsquo;s promises, especially when dealing with large heaps.</description></item><item><title>Notes on Prometheus's TSDB</title><link>https://flaneur2020.github.io/posts/2020-07-18-prometheus-tsdb/</link><pubDate>Sat, 18 Jul 2020 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2020-07-18-prometheus-tsdb/</guid><description>Prometheus is the most popular monitoring solution today. It can scrape metrics from various targets and store them in a time series database, providing flexible aggregation and query capabilities. This article attempts to organize the storage and indexing structure of Prometheus, understanding how it supports complex aggregation queries.
Storage of Time Series Data In Prometheus&amp;rsquo;s presentation, the design of TSDB storage has these challenges:
Metric data follows a &amp;ldquo;Writes are vertical, reads are horizontal&amp;rdquo; pattern; High churn: In a cloud-native environment, a large number of temporary time series are generated; &amp;ldquo;Writes are vertical, reads are horizontal&amp;rdquo; means that TSDB usually collects metrics at fixed intervals and writes them in.</description></item><item><title>Notes on Kafka: Replication</title><link>https://flaneur2020.github.io/posts/2020-03-07-kafka01-replication/</link><pubDate>Sat, 07 Mar 2020 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2020-03-07-kafka01-replication/</guid><description>Kafka&amp;rsquo;s data reliability totally depends on replication instead of a single-machine fsync. To put it simply, Kafka Replication is designed like this:
Partition is the basic unit of replication. Each Partition has multiple Replicas, one of which is the Leader. The Leader handles all read and write interactions with Consumers, while Followers pull data from the Leader via Fetch RPC. The default.replication.factor parameter determines how many Replicas a Partition in a Topic has.</description></item><item><title>A Study about Graceful Shutdown</title><link>https://flaneur2020.github.io/posts/2020-01-12-note-about-graceful-shutdown/</link><pubDate>Sun, 12 Jan 2020 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2020-01-12-note-about-graceful-shutdown/</guid><description>Graceful Shutdown is supposed to be a solved problem, especially for HTTP transports, where the details had already been handled properly by the application servers. However, I never thought carefully about how to implement graceful shutdown in the context of long-lived TCP connections. Let me have a study about the details on it.
Graceful Shutdown in gunicorn First, let&amp;rsquo;s review the process of Graceful Shutdown in the context of short-lived HTTP connections.</description></item><item><title>Notes on LevelDB: Version</title><link>https://flaneur2020.github.io/posts/2019-09-08-leveldb-version/</link><pubDate>Sun, 08 Sep 2019 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2019-09-08-leveldb-version/</guid><description>The term &amp;ldquo;version&amp;rdquo; in LevelDB is a bit weird. Actually, it refers to the metadata of LevelDB: which sstable files are in each Level, and which WAL files are there. Whenever a new sstable is generated due to compaction, this metadata changes accordingly. Changes to this metadata must be logged (in the MANIFEST file) for crash recovery. LevelDB allows others to access the database using older metadata at the same time, so multiple versions of metadata can exist simultaneously.</description></item><item><title>Notes on Linux Container Networking</title><link>https://flaneur2020.github.io/posts/2019-03-29-note-on-basic-container-network/</link><pubDate>Fri, 29 Mar 2019 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2019-03-29-note-on-basic-container-network/</guid><description>Container networking has changed a bit compared to the past virtualization of virtual machine networks. In the past, virtual machine network virtualization had to simulate NIC devices and the hardware details of virtual network cards. In the container era, network virtualization will reuse more of Linux&amp;rsquo;s existed network devices, which can be routed at the third layer of the protocol stack without going through hardware simulation from the very bottom. Another issue is the scalability of the network.</description></item><item><title>Quick note on mruby GC</title><link>https://flaneur2020.github.io/posts/2013-08-31-quick-note-on-mruby-gc/</link><pubDate>Sat, 31 Aug 2013 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/posts/2013-08-31-quick-note-on-mruby-gc/</guid><description>Recently, I went through the mruby GC and basically figured out the logic. Besides patching up some comments, I&amp;rsquo;ll jot down a quick note here.
Tri-color GC If you&amp;rsquo;ve worked with Rails, you might remember that the main issue with traditional Mark-Sweep is the uncontrollable collection time [1]. If you&amp;rsquo;re unlucky enough to catch a GC, page latency can be pretty high. mruby, like lua, targets an embeddable interpreter, so it naturally considers making GC incremental.</description></item><item><title>About</title><link>https://flaneur2020.github.io/_about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/_about/</guid><description>Hi, I&amp;rsquo;m Yazhou Li.
I&amp;rsquo;m a software engineer who loves building distributed architectures and exploring AI/LLM systems. This blog is where I record experiments, practical notes, and the lessons I pick up.
Thanks for reading—feel free to reach out if something resonates.
You can also find me on:
🐙 GitHub 🐦 X 🌐 Bluesky 📷 Instagram 💼 LinkedIn</description></item><item><title>Book Notes</title><link>https://flaneur2020.github.io/booknotes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/booknotes/</guid><description>聪明的投资者 (8) 2018-05-19
Designing Data-Intensive Applications (4) 2018-05-13
投资中最简单的事 (5) 2018-05-04
供给的逻辑 (1) 2018-04-12
逃不开的经济周期 (1) 2018-04-01
图解服务器端网络架构 (1) 2018-03-30
斯坦福极简经济学 (3) 2018-03-10
政治的逻辑 (4) 2018-03-04
原则 (5) 2018-01-17
大数据之路 (1) 2018-01-08
在苍茫中传灯 (4) 2018-01-06
巴菲特传（纪念版） (1) 2017-12-30
中产阶级如何保护自己的财富 (1) 2017-12-29
指数基金投资指南 (4) 2017-12-22
模式分类 (2) 2017-12-01
深度学习 (1) 2017-12-01
我看电商 (2) 2017-12-01
数据挖掘导论 (1) 2017-11-26
中国国家治理的制度逻辑 (2) 2017-11-18
漫步华尔街 (2) 2017-11-18
尽在双11：阿里巴巴技术演进与超越 (2) 2017-11-07
共同基金常识 (3) 2017-11-04
企业IT架构转型之道：阿里巴巴中台战略思想与架构实战 (6) 2017-11-04</description></item><item><title>Links</title><link>https://flaneur2020.github.io/links/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/links/</guid><description>Feel free to DM me on X if you&amp;rsquo;d like to exchange links!
KC的废墟堆
CodeColorist
Lieo
猫·仁波切
熊叔
Davelv
Xuanwo&amp;rsquo;s Blog
邹扒皮实验室
银色子弹
风空之岛
xiaohanyu
飞林沙
Reus
Reflector
hotteran
huangz
chain</description></item><item><title>基于 Bochs 的操作系统内核实现</title><link>https://flaneur2020.github.io/paper/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://flaneur2020.github.io/paper/</guid><description>基于 Bochs 的操作系统内核实现 [fleuria] 2012
简介 Bochs 简介 Bochs(读音Box)是一个开源的模拟器(Emulator)，它可以完全模拟x86/x64的硬件以及一些外围设备。与VirtualBox / VMware等虚拟机(Virtual Machine)产品不同，它的设计目标在于模拟一台真正的硬件，并不追求执行速度的高效，而追求模拟环境的真实，同时带有强大的调试功能，比如观察寄存器、对实地址/虚拟地址下断点、装载符号表等等。对于操作系统内核的开发者而言，是一只不可多得的强力工具，通过简单的设置，即可大大地降低内核开发与调试的困难。
作为开源软件，我们可以很方便地获取它：
主页：http://bochs.sourceforge.net/getcurrent.html 参考文档: http://wiki.osdev.org/Bochs 安装 在Ubuntu操作系统下，可以通过apt-get来安装：
sudo apt-get install bochs 若要利用Bochs的调试功能，则需要自己编译安装：
wget http://sourceforge.net/projects/bochs/files/bochs/2.5.1/bochs-2.5.1.tar.gz/download -O bochs.tar.gz tar -xvfz bochs.tar.gz cd bochs-2.5.1 ./configure --enable-debugger --enable-debugger-gui --enable-disasm --with-x --with-term make sudo cp ./bochs /usr/bin/bochs-dbg 配置 Bochs 提供了许多配置选项，在项目中，我们可以灵活的选择/设置自己所需的功能，比如模拟器的内存大小、软/硬盘镜像以及引导方式等等。而这些配置选项都统一在一个.bochsrc文件中，样例如下：
.bochsrc:
# BIOS与VGA镜像 romimage: file=/usr/share/bochs/BIOS-bochs-latest vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latest # 内存大小 megs: 128 # 软盘镜像 floppya: 1_44=bin/kernel.images, status=inserted # 硬盘镜像 ata0-master: type=disk, path=&amp;quot;bin/rootfs.images&amp;quot;, mode=flat, cylinders=2, heads=16, spt=63 # 引导方式(软盘) boot: a # 日志输出 log: .</description></item></channel></rss>