<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Xing Liu’s Home Page</title><description>Everything Xing Liu (刘星) writes on xingliu.me, in full: notes on LLM inference, books, crypto and life.</description><link>https://xingliu.me/</link><language>en</language><atom:link href="https://xingliu.me/feed.xml" rel="self" type="application/rss+xml"/><item><title>Neuron Learning Notes</title><link>https://xingliu.me/2026/03/10/neuron-learning-notes/</link><guid isPermaLink="true">https://xingliu.me/2026/03/10/neuron-learning-notes/</guid><description>Notes on AWS Trainium and NKI: the memory hierarchy, data representation, indexing, tiling, DMA and logical NeuronCores.</description><pubDate>Tue, 10 Mar 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;trainium-memory-hierarchy&quot;&gt;Trainium Memory Hierarchy&lt;/h2&gt;
&lt;h3 id=&quot;host-memory&quot;&gt;Host Memory&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;external, DRAM&lt;/li&gt;
&lt;li&gt;Linear Memory: multi-dimensional tensors must be stored in a flattened manner&lt;/li&gt;
&lt;li&gt;~1TB, ~16GB/s&lt;/li&gt;
&lt;li&gt;NKI kernels don’t provide API to access it&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;device-memory&quot;&gt;Device Memory&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;external, HMB&lt;/li&gt;
&lt;li&gt;Linear Memory&lt;/li&gt;
&lt;li&gt;~50GB, 0.5TB/s per NC&lt;/li&gt;
&lt;li&gt;Input and output parameters of a NKI kernel must from and to Device Memory&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;sbuf-state-buffer&quot;&gt;SBUF (State Buffer)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;internal, two-dimensional memory&lt;/li&gt;
&lt;li&gt;128 partition&lt;/li&gt;
&lt;li&gt;~25MB, ~10TB/s&lt;/li&gt;
&lt;li&gt;NKI kernel load data from HBM to SBUF, and result from SBUF to HBM&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;psum-partial-sum-buffer&quot;&gt;PSUM (Partial Sum Buffer)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;internal, two-dimensional memory&lt;/li&gt;
&lt;li&gt;128 partition&lt;/li&gt;
&lt;li&gt;~2MB, 10TB/s&lt;/li&gt;
&lt;li&gt;Store MatMul result from TensorE&lt;/li&gt;
&lt;li&gt;PSUM can be accessed by ScalarE and VectorE, but for performance, leave it to TensorE.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;data-representation&quot;&gt;Data Representation&lt;/h2&gt;
&lt;h3 id=&quot;representing-data-in-nki&quot;&gt;Representing data in NKI&lt;/h3&gt;
&lt;p&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tensor&lt;/code&gt; has a name, a shape that describes the number and size of each of its dimensions, an element data type (or “dtype”), and a description of the physical location of the underlying data on the NeuronCore.&lt;/p&gt;
&lt;p&gt;For tensor placement, a physical location is defined by &lt;strong&gt;memory type + offset/size metadata&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;HBM (1D memory)&lt;/strong&gt;, you use one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(offset, size)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;strong&gt;SBUF/PSUM (2D memories)&lt;/strong&gt;, you use two &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(offset, size)&lt;/code&gt; pairs describing a rectangle:
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Partition offset/size&lt;/strong&gt; (units: partitions) — which partitions are used.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In-partition offset/size&lt;/strong&gt; (units: bytes) — where data starts and how many bytes are used inside each selected partition.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;128×64&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float16&lt;/code&gt; tensor mapped row-wise to SBUF:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;partition &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(offset, size)&lt;/code&gt; could be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(0, 128)&lt;/code&gt; (128 rows across 128 partitions),&lt;/li&gt;
&lt;li&gt;in-partition &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(offset, size)&lt;/code&gt; could be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(1024, 128)&lt;/code&gt; because each row has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;64 × 2 = 128&lt;/code&gt; bytes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;indexing&quot;&gt;Indexing&lt;/h2&gt;
&lt;h3 id=&quot;basic-tensor-indexing&quot;&gt;Basic Tensor Indexing&lt;/h3&gt;
&lt;p&gt;NKI supports basic indexing of tensors using integers as indexes.&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;x = nl.ndarray((2, 128, 1024), dtype=nl.float32, buffer=nl.hbm)

# `x[1, :, :]` is the same as `x[1]`
assert x[1, :, :].shape == [128, 1024]

# Get a smaller view of the third dimension
assert x[1, :, 0:512].shape == [128, 512]

# `x[:, 1, 0:2]` returns a view of x with shape of [2, 2]
# [[x[0, 1, 0], x[0, 1 ,1]], [x[1, 1, 0], x[1, 1 ,1]]]
assert x[:, 1, 0:2].shape == [2, 2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;tiling&quot;&gt;Tiling&lt;/h2&gt;
&lt;h3 id=&quot;tile-based-operations&quot;&gt;Tile-based operations&lt;/h3&gt;
&lt;p&gt;SBUF and PSUM memories have 128 partitions, most APIs are limited to tiles with a first dimension (also called the “Partition Dimension”) no larger than 128 elements.&lt;/p&gt;
&lt;h3 id=&quot;layout-considerations&quot;&gt;Layout considerations&lt;/h3&gt;
&lt;p&gt;SBUF and PSUM all have first dimension as the partition dimention with size 128. The second dimension is the free dimension.&lt;/p&gt;
&lt;p&gt;ow-major layouts place elements within each row in contiguous memory, and column-major layouts place elements within each column in contiguous memory.&lt;/p&gt;
&lt;p&gt;The NeuronCore compute engines impose two layout constraints (LC):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Layout Constraint #1] For matrix multiplication operations, the contraction axis of both input tiles must be mapped to the Partition (P or P_DIM) dimension which is typically 128 for current hardware.&lt;/li&gt;
&lt;li&gt;[Layout Constraint #2] For operations that are not matrix multiplication operations, such as scalar or vector operations, the parallel axis should be mapped to the Partition (P or P_DIM) dimension.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tile-size-considerations&quot;&gt;Tile Size Considerations&lt;/h3&gt;
&lt;p&gt;Besides layout constraints, NeuronCore hardware further imposes three tile-size constraints (TC) in NKI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[Tile-Size Constraint#1] The P dimension size of a tile in both SBUF and PSUM must never exceed nki.tile_size.pmax == 128.&lt;/li&gt;
&lt;li&gt;[Tile-Size Constraint#2] For tiles in PSUM, the F dimension size must not exceed nki.tile_size.psum_fmax == 512.&lt;/li&gt;
&lt;li&gt;[TileSize Constraint#3] Matrix multiplication input tiles F dimension size must not exceed nki&lt;wbr&gt;.tile_size&lt;wbr&gt;.gemm_stationary_fmax == 128 on the left-hand side (LHS), or nki&lt;wbr&gt;.tile_size&lt;wbr&gt;.gemm_moving_fmax == 512 on the right-hand side (RHS).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;introduction-to-direct-memory-access-dma&quot;&gt;Introduction to Direct Memory Access (DMA)&lt;/h2&gt;
&lt;p&gt;Direct Memory Access (DMA) engines in Neuron enable efficient data movement between different memory types, primarily between the device memory (HBM) and on-chip SRAM buffers (SBUF).&lt;/p&gt;
&lt;h3 id=&quot;basic-dma-capabilities&quot;&gt;Basic DMA Capabilities&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Each DMA transfer starts with a DMA trigger from a NeuronCore and ends with a semaphore update from the DMA engine to signal the completion of transfer back to the NeuronCore&lt;/li&gt;
&lt;li&gt;DMA transfers can perform both copy and transpose transfers into SBUF.&lt;/li&gt;
&lt;li&gt;DMA transfers can move data in multiple directions: bidirectionally between HBM to SBUF, within HBM or within SBUF&lt;/li&gt;
&lt;li&gt;DMA engines also support scatter-gather operations, allowing a single transfer to gather data from multiple non-contiguous source buffers or scatter to multiple non-contiguous destination buffers.&lt;/li&gt;
&lt;li&gt;Bandwidth
&lt;ul&gt;
&lt;li&gt;27.2 GB/s for NeuronCore-v2 and -v3&lt;/li&gt;
&lt;li&gt;38.4 GB/s for NeuronCore-v4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;dma-triggers&quot;&gt;DMA Triggers&lt;/h3&gt;
&lt;p&gt;DMA transfers can be triggered by any engine sequencer in the NeuronCore.&lt;/p&gt;
&lt;h3 id=&quot;dma-queues&quot;&gt;DMA Queues&lt;/h3&gt;
&lt;p&gt;DMA transfers are submitted to DMA queues for the DMA Engines to consume. There are 16 DMA queues per DMA engine (ID 0-15).&lt;/p&gt;
&lt;h3 id=&quot;performance-considerations&quot;&gt;Performance Considerations&lt;/h3&gt;
&lt;p&gt;Higher the bytes per partition, higher the bandwidth. Each DMA engine are responsible for 8 partitions.&lt;/p&gt;
&lt;h2 id=&quot;using-logical-neuron-cores-lnc&quot;&gt;Using Logical Neuron Cores (LNC)&lt;/h2&gt;
&lt;p&gt;The Neuron SDK supports running NKI kernels on multiple logical cores.&lt;/p&gt;</content:encoded><category>LLM inference</category></item><item><title>Nano-vLLM Study Notes</title><link>https://xingliu.me/2026/01/23/nano-vllm-notes/</link><guid isPermaLink="true">https://xingliu.me/2026/01/23/nano-vllm-notes/</guid><description>A file-by-file tour of nano-vLLM: the scheduler, block manager, model runner, tensor parallelism and Qwen3.</description><pubDate>Fri, 23 Jan 2026 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been recently studying the nano-vLLM codebase and writing this article to document my notes and learnings for future reference.&lt;/p&gt;
&lt;h2 id=&quot;configpy&quot;&gt;config.py&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;model: path to the model weight and config files.&lt;/li&gt;
&lt;li&gt;max_num_batched_tokens: The maximum total number of tokens that can be processed in a &lt;strong&gt;single batch across all sequences&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;max_num_seqs: The maximum number of sequences (requests) that can be processed simultaneously in a batch.&lt;/li&gt;
&lt;li&gt;max_model_len: The maximum length (in tokens) of a single sequence.&lt;/li&gt;
&lt;li&gt;gpu_memory_utilization: The fraction of GPU memory to use (90% by default).&lt;/li&gt;
&lt;li&gt;tensor_parallel_size: tensor parallelism.&lt;/li&gt;
&lt;li&gt;enforce_eager: eager mode.&lt;/li&gt;
&lt;li&gt;hf_config: The HuggingFace model configuration object.&lt;/li&gt;
&lt;li&gt;eos: likely the end-of-sequence token ID.&lt;/li&gt;
&lt;li&gt;kvcache_block_size: The size of each block in the key-value cache. Must be multiple of 256.&lt;/li&gt;
&lt;li&gt;num_kvcache_blocks: likely the total number of KV-cache blocks to allocate.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;sampling_paramspy&quot;&gt;sampling_params.py&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;temperature&lt;/li&gt;
&lt;li&gt;max_tokens&lt;/li&gt;
&lt;li&gt;ignore_eos&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;benchpy&quot;&gt;bench.py&lt;/h2&gt;
&lt;p&gt;The script generates random token sequences, feeds them to a language model, and measures throughput.&lt;/p&gt;
&lt;h2 id=&quot;enginesequencepy&quot;&gt;engine/sequence.py&lt;/h2&gt;
&lt;p&gt;This file implements a Sequence class that represents a single request/prompt being processed by the inference engine.&lt;/p&gt;
&lt;p&gt;Attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;seq_id: Unique id.&lt;/li&gt;
&lt;li&gt;status: waiting, running, finished.&lt;/li&gt;
&lt;li&gt;token_ids: full list of tokens.&lt;/li&gt;
&lt;li&gt;rest of the token ids, sampling params.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multiple token ids, block counts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;engineblock_managerpy&quot;&gt;engine/block_manager.py&lt;/h2&gt;
&lt;p&gt;Block class for a single block:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;block_id&lt;/li&gt;
&lt;li&gt;ref_count: int (for prefix caching)&lt;/li&gt;
&lt;li&gt;hash: int (for prefix caching)&lt;/li&gt;
&lt;li&gt;token_ids: list[int]&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;BlockManager class for orchestration and prefix caching:&lt;br&gt;
Attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;block_size: int&lt;/li&gt;
&lt;li&gt;blocks: list[Block]&lt;/li&gt;
&lt;li&gt;hash_to_block_id: dict[int, int]&lt;/li&gt;
&lt;li&gt;free_block_ids: deque[int]&lt;/li&gt;
&lt;li&gt;used_block_ids: deque[int]&lt;/li&gt;
&lt;li&gt;allocate:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;allocate&lt;/li&gt;
&lt;li&gt;deallocate&lt;/li&gt;
&lt;li&gt;can_allocate&lt;/li&gt;
&lt;li&gt;can_append&lt;/li&gt;
&lt;li&gt;may_append&lt;/li&gt;
&lt;li&gt;compute_hash&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;utilscontextpy&quot;&gt;utils/context.py&lt;/h2&gt;
&lt;p&gt;Context to share globle state info across different part of the inference engine.&lt;/p&gt;
&lt;p&gt;Attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is_prefill: whether it’s in prefill phase&lt;/li&gt;
&lt;li&gt;cu_seqlens_q: Cumulative sequence lengths for queries for FlashAttention&lt;/li&gt;
&lt;li&gt;cu_seqlens_k: Cumulative sequence lengths for keys for FlashAttention&lt;/li&gt;
&lt;li&gt;max_seqlen_q: Maximum query sequence length in the current batch&lt;/li&gt;
&lt;li&gt;max_seqlen_k: Maximum key sequence length in the current batch&lt;/li&gt;
&lt;li&gt;slot_mapping: token to physical KV cache slots mapping&lt;/li&gt;
&lt;li&gt;context_lens: Number of cached tokens for each sequence&lt;/li&gt;
&lt;li&gt;block_tables: Maps each sequence to its allocated memory blocks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Glable Context instance, set and reset.&lt;/p&gt;
&lt;h2 id=&quot;engineschedulerpy&quot;&gt;engine/scheduler.py&lt;/h2&gt;
&lt;p&gt;The brain of continuous batching. It maintains queues for waiting and running sequences. It decides how many sequences from the waiting queue can be processed in the “prefill” phase, and which running sequences can proceed in the “decode” phase without exceeding the GPU’s KV cache capacity. It also handles “preemption” (pausing a sequence if the engine runs out of memory)&lt;/p&gt;
&lt;p&gt;Methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is_finished(): Returns True if both queues are empty, meaning the engine has no more work to do.&lt;/li&gt;
&lt;li&gt;add(seq: Sequence): Accepts a new incoming request (Sequence) and puts it at the back of the waiting queue.&lt;/li&gt;
&lt;li&gt;Schedule(): This method is called before every forward pass of the model. It decides what the model will compute next. It returns a tuple containing the list of sequences to process and a boolean indicating if it’s doing a Prefill (True) or Decode (False).&lt;/li&gt;
&lt;li&gt;preempt(): When a sequence is preempted due to lack of memory.&lt;/li&gt;
&lt;li&gt;postprocess(): After the model generates the next tokens (token_ids), this method applies them to the sequences.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;max_num_seqs limits how many requests (sequences) can be scheduled in one iteration, while max_num_batched_tokens limits total prompt tokens during prefill. Prefill is batched: in one scheduling step, it can schedule multiple waiting requests together, stopping when it hits sequence limit, token limit, or KV-cache allocation limit. Decode also schedules multiple running sequences (typically one token each), and is constrained by max_num_seqs plus KV-cache append capacity rather than max_num_batched_tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;enginellm_enginepy&quot;&gt;engine/llm_engine.py&lt;/h2&gt;
&lt;p&gt;It defines the LLMEngine class — the central orchestrator of the nano-vllm inference engine. It ties together model execution, scheduling, tokenization, and multi-process tensor parallelism into a unified interface for running LLM inference.&lt;/p&gt;
&lt;h3 id=&quot;engine-initialization&quot;&gt;Engine Initialization&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Config construction: Filters kwargs to only pass recognized fields to the Config dataclass&lt;/li&gt;
&lt;li&gt;Tensor parallelism setup: Rank0 has its own ModelRunner, worker processes created for rank 1 and above.&lt;/li&gt;
&lt;li&gt;Tokenizer&lt;/li&gt;
&lt;li&gt;Scheduler&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;exit&quot;&gt;exit&lt;/h3&gt;
&lt;p&gt;Sends an “exit” command to the model runner (which propagates to all worker processes), then waits for all child processes to terminate with join().&lt;/p&gt;
&lt;h3 id=&quot;add_request&quot;&gt;add_request&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Accepts a prompt as either a string (which gets tokenized) or pre-tokenized token IDs.&lt;/li&gt;
&lt;li&gt;Wraps it in a Sequence object (which tracks state like generated tokens, finish status, etc.).&lt;/li&gt;
&lt;li&gt;Adds it to the scheduler’s queue.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step&quot;&gt;step&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;scheduler.schedule(): Selects a batch of sequences to run and determines whether this is a prefill or decode&lt;/li&gt;
&lt;li&gt;execute forward pass with model runner&lt;/li&gt;
&lt;li&gt;scheduler.postprocess(): Updates sequences with the newly generated tokens and marks finished sequences.&lt;/li&gt;
&lt;li&gt;Return: completed sequences and a throughput metric: positive for prefill, negative for decode.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;generate&quot;&gt;generate&lt;/h3&gt;
&lt;p&gt;This is the user-facing method that runs end-to-end generation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Input normalization: If a single SamplingParams is provided, it’s broadcast to all prompts.&lt;/li&gt;
&lt;li&gt;Enqueuing: All prompts are added to the scheduler via add_request.&lt;/li&gt;
&lt;li&gt;Main loop: Repeatedly calls step() until all sequences finish.&lt;/li&gt;
&lt;li&gt;Throughput tracking (with tqdm)&lt;/li&gt;
&lt;li&gt;Output assembly&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;enginemodel_runnerpy&quot;&gt;engine/model_runner.py&lt;/h2&gt;
&lt;p&gt;ModelRunner is the workhorse that actually runs the LLM on a GPU. It handles model loading, KV cache allocation, input preparation for both prefill and decode phases, CUDA graph capture for decode acceleration, and tensor-parallel coordination across multiple GPUs via NCCL and shared memory.&lt;/p&gt;
&lt;h3 id=&quot;initialization&quot;&gt;Initialization&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;NCCL init: establishes GPU-to-GPU communication&lt;/li&gt;
&lt;li&gt;Device binding&lt;/li&gt;
&lt;li&gt;Model creation: Instantiates model with the HuggingFace config, then loads pretrained weights via load_model()&lt;/li&gt;
&lt;li&gt;Sampler creation: Creates a Sampler that converts logits → token IDs using temperature-scaled softmax + Gumbel sampling.&lt;/li&gt;
&lt;li&gt;Warmup: Runs a dummy forward pass to trigger all lazy CUDA/Triton kernel compilation&lt;/li&gt;
&lt;li&gt;KV cache allocation: allocate_kv_cache() — uses the peak memory measurement to compute how many KV cache blocks fit in remaining GPU memory&lt;/li&gt;
&lt;li&gt;CUDA graph capture&lt;/li&gt;
&lt;li&gt;Tensor parallel setup: If world_size &amp;gt; 1, rank 0 creates a 1 MB shared memory segment (SharedMemory)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;tensor-parallel-communication&quot;&gt;Tensor Parallel Communication&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The multi-GPU design uses a leader-follower pattern with shared memory + multiprocessing Events&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write_shm&lt;/code&gt;: Serializes a method name + arguments with pickle, writes a 4-byte length header + payload into shared memory, then signals all follower processes via their Events.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read_shm&lt;/code&gt;: Blocks until signaled, deserializes the command, then clears the event.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;call&lt;/code&gt;: When rank 0 calls call(“run”, seqs, is_prefill), it first broadcasts the command to followers, then executes locally. Followers receive the command in loop() and execute the same method. This ensures all ranks execute the same operations in lock-step.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loop&lt;/code&gt;: Non-zero ranks sit in this infinite loop, only breaking on an “exit” command.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;model-warmup&quot;&gt;Model Warmup&lt;/h3&gt;
&lt;p&gt;Creates worst-case dummy sequences (maximum length, maximum batch) and runs a full prefill forward pass.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Triggers all lazy CUDA kernel compilation&lt;/li&gt;
&lt;li&gt;Records peak memory usage so allocate_kv_cache knows how much memory the model needs&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;kv-cache-allocation&quot;&gt;KV Cache Allocation&lt;/h3&gt;
&lt;h3 id=&quot;input-preparation&quot;&gt;Input Preparation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;prepare_prefill: This builds inputs compatible with Flash Attention’s variable-length API&lt;/li&gt;
&lt;li&gt;prepare_decode: All tensors are created with pin_memory=True and transferred with .cuda(non_blocking=True) for overlapped CPU→GPU transfers.&lt;/li&gt;
&lt;li&gt;prepare_sample: Collects per-sequence temperature values into a tensor for the sampler.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;model-execution&quot;&gt;Model Execution&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Prefill or eager or batch &amp;gt; 512: Eager execution&lt;/li&gt;
&lt;li&gt;Decode with batch ≤ 512: CUDA graph replay&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cuda-graph-capture&quot;&gt;CUDA Graph Capture&lt;/h3&gt;
&lt;h2 id=&quot;layersattentionpy&quot;&gt;layers/attention.py&lt;/h2&gt;
&lt;p&gt;This file implements the attention layer for a minimal vLLM-style inference engine. It has three components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Triton GPU kernel for writing KV data into a paged KV cache&lt;/li&gt;
&lt;li&gt;A Python wrapper that launches that kernel&lt;/li&gt;
&lt;li&gt;An Attention module that orchestrates KV caching and dispatches to FlashAttention for both prefill and decode phases&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-triton-kernel&quot;&gt;The Triton Kernel&lt;/h3&gt;
&lt;p&gt;A GPU kernel written in Triton that copies newly computed key/value vectors into the paged KV cache.&lt;/p&gt;
&lt;h3 id=&quot;the-python-wrapper&quot;&gt;The Python Wrapper&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Shape extraction: key has shape [N, num_heads, head_dim] where N = total tokens in the batch.&lt;/li&gt;
&lt;li&gt;Stride assertions: Verifies the tensors are contiguous in the expected layout — the last dimension (head_dim) must be contiguous (stride 1), and the num_heads dimension must have stride head_dim. This ensures the kernel can treat num_heads × head_dim as a single flat vector of size D.&lt;/li&gt;
&lt;li&gt;Launch: [(N,)] launches N thread blocks — one per token.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-attention-module&quot;&gt;The Attention Module&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Stores attention hyperparameters&lt;/li&gt;
&lt;li&gt;self.k_cache and self.v_cache are initialized as empty tensors. They get replaced later by the ModelRunner with properly sized paged cache buffers allocated by the block manager.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;layerslinearpy--layersembed_headpy&quot;&gt;layers/linear.py &amp;amp; layers/embed_head.py&lt;/h2&gt;
&lt;p&gt;Tensor Parallelism in nano-vllm&lt;/p&gt;
&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;
&lt;p&gt;These two files implement &lt;strong&gt;Megatron-LM style tensor parallelism (TP)&lt;/strong&gt;, splitting model weights across GPUs to serve large language models. The core pattern is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Column-parallel (no comm) → local compute → Row-parallel (all-reduce)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Each transformer sub-block (attention, MLP) requires only &lt;strong&gt;one all-reduce&lt;/strong&gt;, minimizing communication overhead.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;linear-layers-linearpy&quot;&gt;Linear Layers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;linear.py&lt;/code&gt;)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;Class&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Sharding&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Communication&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ReplicatedLinear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;None (full copy)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Small layers not worth splitting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ColumnParallelLinear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output dim (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dim=0&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;First projection (Q/K/V, gate, up)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MergedColumnParallelLinear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output dim (multiple merged)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Fused gate + up proj&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QKVParallelLinear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Output dim (Q/K/V merged)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Fused QKV with GQA support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RowParallelLinear&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Input dim (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dim=1&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Second projection (o_proj, down_proj)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;key-mechanisms&quot;&gt;Key Mechanisms&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;weight_loader&lt;/code&gt; hook&lt;/strong&gt;: Attached to each parameter; called during checkpoint loading to extract the correct shard per GPU via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.narrow()&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.chunk()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Column-parallel&lt;/strong&gt;: Splits output dim → each GPU produces a slice of the output, no communication needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Row-parallel&lt;/strong&gt;: Splits input dim → each GPU computes a partial result, summed via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;. Bias added only on rank 0 to avoid double-counting.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;qkv-weight-layout-per-gpu&quot;&gt;QKV Weight Layout (per GPU)&lt;/h4&gt;
&lt;p&gt;For GQA (e.g., 8 Q heads, 2 KV heads, tp_size=2):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[Q_shard (4 heads) | K_shard (1 head) | V_shard (1 head)]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Loaded via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;loaded_shard_id ∈ {&quot;q&quot;, &quot;k&quot;, &quot;v&quot;}&lt;/code&gt; with computed offsets.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;embedding--lm-head-embed_headpy&quot;&gt;Embedding &amp;amp; LM Head (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;embed_head.py&lt;/code&gt;)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;Class&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Sharding&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Communication&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VocabParallelEmbedding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vocab rows&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Input token embeddings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParallelLMHead&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vocab rows&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gather&lt;/code&gt; to rank 0&lt;/td&gt;
&lt;td&gt;Output logits for sampling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&quot;embedding-forward&quot;&gt;Embedding Forward&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mask&lt;/strong&gt; tokens outside this rank’s vocab range.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remap&lt;/strong&gt; global token IDs to local indices.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lookup&lt;/strong&gt; embeddings, zero out masked positions.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;All-reduce&lt;/strong&gt; to combine (each token is non-zero on exactly one rank).&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id=&quot;lm-head-forward&quot;&gt;LM Head Forward&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Prefill optimization&lt;/strong&gt;: Extract only the last token per sequence (only those need logits).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linear projection&lt;/strong&gt; with this rank’s vocab shard → partial logits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gather to rank 0&lt;/strong&gt; and concatenate → only rank 0 has full logits for sampling. Other ranks return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;end-to-end-transformer-layer-flow&quot;&gt;End-to-End Transformer Layer Flow&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Input (identical on all GPUs)
  │
  ├─► QKVParallelLinear (column, no comm)
  │     └─► Attention (local)
  │           └─► RowParallelLinear/o_proj (all_reduce) ──► + residual
  │
  ├─► MergedColumnParallelLinear/gate+up (column, no comm)
  │     └─► SiLU(gate) * up (local)
  │           └─► RowParallelLinear/down_proj (all_reduce) ──► + residual
  │
  └─► (repeat N layers) ─► ParallelLMHead (gather to rank 0) ─► Sampling
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;design-principles&quot;&gt;Design Principles&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Minimize communication&lt;/strong&gt;: Column + Row pairing ensures only one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt; per sub-block.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decoupled loading&lt;/strong&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;weight_loader&lt;/code&gt; hooks let each GPU extract its shard from full checkpoint weights independently.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Asymmetric head output&lt;/strong&gt;: Embedding uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt; (all GPUs need embeddings), LM head uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gather&lt;/code&gt; (only rank 0 samples), saving memory.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;modelsqwen3py&quot;&gt;models/qwen3.py&lt;/h2&gt;
&lt;p&gt;Implementation of the Qwen3 causal language model for the nano-vllm inference engine, with tensor parallelism (TP) and KV caching support.&lt;/p&gt;
&lt;h3 id=&quot;architecture&quot;&gt;Architecture&lt;/h3&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Qwen3ForCausalLM              # top-level entry point
  └─ Qwen3Model               # embedding + N decoder layers + final norm
       └─ Qwen3DecoderLayer    # single transformer block
            ├─ Qwen3Attention  # GQA + RoPE + optional QK-norm
            └─ Qwen3MLP       # gated SiLU (SwiGLU) FFN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;classes&quot;&gt;Classes&lt;/h3&gt;
&lt;h4 id=&quot;qwen3attention&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3Attention&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Multi-head attention with &lt;strong&gt;Grouped-Query Attention (GQA)&lt;/strong&gt; — fewer KV heads than Q heads to reduce memory.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qkv_proj&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QKVParallelLinear&lt;/code&gt;): Fused Q/K/V projection in one matmul, column-sharded across GPUs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;o_proj&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RowParallelLinear&lt;/code&gt;): Output projection, row-sharded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rotary_emb&lt;/code&gt;&lt;/strong&gt;: Applies RoPE positional encoding via a precomputed cos/sin cache.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attn&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Attention&lt;/code&gt;): FlashAttention with KV cache — uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flash_attn_varlen_func&lt;/code&gt; for prefill and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flash_attn_with_kvcache&lt;/code&gt; for decode.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q_norm&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k_norm&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RMSNorm&lt;/code&gt;): Per-head QK normalization, active only when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qkv_bias=False&lt;/code&gt; (Qwen3 default).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;qwen3mlp&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3MLP&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Gated SiLU (SwiGLU) feed-forward network.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gate_up_proj&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MergedColumnParallelLinear&lt;/code&gt;): Fused gate + up projection, column-sharded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;down_proj&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RowParallelLinear&lt;/code&gt;): Down projection, row-sharded with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;act_fn&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiluAndMul&lt;/code&gt;): Splits output in half, applies &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiLU(gate) * up&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;qwen3decoderlayer&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3DecoderLayer&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Single transformer block with &lt;strong&gt;Pre-RMSNorm&lt;/strong&gt; and a &lt;strong&gt;fused residual add&lt;/strong&gt; optimization.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RMSNorm.add_rms_forward&lt;/code&gt; method fuses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;residual = x + old_residual&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x = RMSNorm(residual)&lt;/code&gt; into one compiled pass, reducing memory overhead.&lt;/li&gt;
&lt;li&gt;The residual tensor is passed between layers as a separate stream.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;qwen3model&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3Model&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Transformer backbone.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;embed_tokens&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VocabParallelEmbedding&lt;/code&gt;): Vocabulary sharded across GPUs, combined via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layers&lt;/code&gt;&lt;/strong&gt;: Stack of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3DecoderLayer&lt;/code&gt; modules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;norm&lt;/code&gt;&lt;/strong&gt;: Final RMSNorm that folds in the last residual.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;qwen3forcausallm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Qwen3ForCausalLM&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Top-level model class.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;packed_modules_mapping&lt;/code&gt;&lt;/strong&gt;: Maps original checkpoint weight names (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;q_proj&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;k_proj&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v_proj&lt;/code&gt;) to fused parameter names (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qkv_proj&lt;/code&gt;) for weight loading.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lm_head&lt;/code&gt;&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ParallelLMHead&lt;/code&gt;): Projects hidden states to vocab logits; gathers across TP ranks.&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;weight tying&lt;/strong&gt; between embedding and LM head.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;key-design-patterns&quot;&gt;Key Design Patterns&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;Pattern&lt;/th&gt;
&lt;th scope=&quot;col&quot;&gt;Details&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tensor Parallelism&lt;/td&gt;
&lt;td&gt;Column-parallel for Q/K/V/gate/up; row-parallel + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;all_reduce&lt;/code&gt; for O/down&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fused Projections&lt;/td&gt;
&lt;td&gt;QKV in one linear; gate + up in one linear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fused Residual + Norm&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RMSNorm&lt;/code&gt; combines residual addition and normalization in a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@torch.compile&lt;/code&gt;d kernel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KV Caching&lt;/td&gt;
&lt;td&gt;Triton kernel for cache storage; FlashAttention for prefill and paged decode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GQA&lt;/td&gt;
&lt;td&gt;Fewer KV heads than Q heads to reduce memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QK Normalization&lt;/td&gt;
&lt;td&gt;Per-head RMSNorm on Q and K (active when no QKV bias)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;</content:encoded><category>LLM inference</category></item><item><title>From Training Paradigms to Inference-First Engineering</title><link>https://xingliu.me/2025/10/09/from-training-paradigms-to-inference-first-engineering/</link><guid isPermaLink="true">https://xingliu.me/2025/10/09/from-training-paradigms-to-inference-first-engineering/</guid><description>Why time to first token, inter-token latency and throughput, not training, now set the agenda for AI engineering.</description><pubDate>Thu, 09 Oct 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For years, the AI research community was fixated on training dynamics: scaling laws, novel architectures, and loss minimization. While foundational, this focus has created a fleet of powerful models that are fundamentally misaligned with production constraints. We’re shifting into an inference-first era, where the core metrics dictating a model’s utility are Time to First Token for perceived responsiveness, inter-token latency for conversational flow, and overall throughput. The success of generative AI now hinges on solving a complex, multi-dimensional optimization problem across the entire serving stack, from silicon to the user.&lt;/p&gt;
&lt;p&gt;This optimization challenge is being met with a full-stack approach that is reshaping deployment architecture. At the hardware level, we’re moving towards custom ASICs, exploited by compiler frameworks like TensorRT-LLM that fuse operations into optimized kernels. These are paired with algorithmic techniques like quantization and speculative decoding. The direct result of this intense optimization is the fragmentation of deployment strategies beyond massive, centralized models. We can now create expertly distilled, specialist models and even enable powerful on-device inference for applications with strict privacy and latency requirements. The architectural paradigm is shifting to a strategic portfolio of models deployed across the cloud-edge continuum.&lt;/p&gt;
&lt;p&gt;Looking further out, a fascinating frontier is the convergence of AI with Web3 infrastructure. This synthesis can solve core challenges in both domains. We envision permissionless, incentivized markets for inference, where compute providers globally contribute to a decentralized serving layer, reducing reliance on centralized cloud providers. In this paradigm, AI can also function as a highly sophisticated oracle for on-chain logic, interpreting complex, unstructured data to trigger smart contracts in ways far beyond simple price feeds.&lt;/p&gt;
&lt;p&gt;This could culminate in sovereign AI agents, entities with their own wallets that can own assets and participate directly in the decentralized economy.&lt;/p&gt;
&lt;p&gt;Ultimately, these technical advancements are fundamentally reshaping the human-computer interaction model. We are moving beyond the simple prompt-response paradigm towards more persistent, stateful, and symbiotic cognitive tools. The next generation of AI will not be a chatbot you query, but an integrated agentic system that assists in complex, multi-step workflows like systems architecture design or scientific discovery. For us as engineers, the mandate is clear: to build the robust, reliable, and aligned systems that can support this future, transforming generative models from impressive novelties into indispensable partners.&lt;/p&gt;</content:encoded><category>LLM inference</category></item><item><title>The meaning of travel</title><link>https://xingliu.me/2025/05/26/the-meaning-of-my-travel/</link><guid isPermaLink="true">https://xingliu.me/2025/05/26/the-meaning-of-my-travel/</guid><description>What travel is for, with notes from Thailand, Nepal and Japan on a 2025 trip through Asia.</description><pubDate>Mon, 26 May 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I have been actively traveling for the past decade. After many trips and many experiences, I was pondering if the purpose of travel has ever changed for me. Luckily, many years ago I learned how to stop posting (most of) my personal life on social media to get “attention.” So now, what’s my purpose of travel?&lt;/p&gt;
&lt;p&gt;To answer that question, let’s take a step back and think about what I want to get from my life. After much reading and thinking, one of my meanings of life is to gain as much experience as possible within my lifespan. With that meaning, everything I do and will do is to serve this purpose. Traveling is one of the means I can gain life experiences.&lt;/p&gt;
&lt;p&gt;To gain different experiences, I wish to see some different and unexpected societies, people, lifestyles, landscapes, animals, and so on. Some unexpected incidents would be a bonus. This is the exact reason I don’t like traveling in most parts of China, since every city is alike and different parts are so artificial, and I understand exactly how most Chinese live.&lt;/p&gt;
&lt;p&gt;Besides seeing different people and societies, another way to gain different experiences is to imagine my life if I were born in this city and country. Humanity is the same, but due to culture, religion, economy, people can have totally different lifestyles, and finding the little living wisdom is always a sparkling moment during traveling. For example, when I realized a hair dryer is a valuable asset in Nepal and found out there is always an emergency light in Japan’s hotel.&lt;/p&gt;
&lt;p&gt;Because of the above reasons, I prefer places that had significant events in the past century. This is because I feel the past century is more relevant to me; WWII is more impactful than ancient Greek civilization or Mayan civilization.&lt;/p&gt;
&lt;p&gt;I will briefly talking about the experiences from the last 3 countries I went to during my 2025 Asia trip:&lt;/p&gt;
&lt;p&gt;Thailand: Compared to my last visit 10 years ago, I’m trying harder to actively experience this country. It’s a lucky and unlucky country, and I felt a huge contradiction.&lt;/p&gt;
&lt;p&gt;Nepal: Probably the most religious country I’ve ever been to. Without material and economic development, religion is indeed one of the few options. People are generally very nice and living on their instincts.&lt;/p&gt;
&lt;p&gt;Japan: Probably the most developed country in the world, the abundance of details and organization are sensational. Nothing is built by magic; people’s hard work is behind it. This could only happen in Asia.&lt;/p&gt;</content:encoded><category>Life &amp; work</category></item><item><title>Be True To Yourself</title><link>https://xingliu.me/2025/03/23/be-true-to-yourself/</link><guid isPermaLink="true">https://xingliu.me/2025/03/23/be-true-to-yourself/</guid><description>A short note on where pain comes from, and on being honest with yourself about your own desires.</description><pubDate>Sun, 23 Mar 2025 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My pain (as is true for many other people) comes from my own desires, which originate entirely from my heart. One of my life goals is to eliminate this pain.&lt;/p&gt;
&lt;p&gt;To understand my desires, I must be true to myself, acknowledge that everything is natural and reasonable, never lie to myself, and accept who I am.&lt;/p&gt;
&lt;p&gt;Interact with the world appropriately and find my own way to comfort and satisfy my desires.&lt;/p&gt;</content:encoded><category>Life &amp; work</category></item><item><title>侦探小说：He’s Replaceable</title><link>https://xingliu.me/2025/01/01/detective/</link><guid isPermaLink="true">https://xingliu.me/2025/01/01/detective/</guid><description>一部中文侦探小说，共六章，发生在 North San Jose 的一家 AI 创业公司。</description><pubDate>Wed, 01 Jan 2025 12:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;hes-replaceable&quot;&gt;He’s Replaceable&lt;/h2&gt;
&lt;h3 id=&quot;正文&quot;&gt;正文&lt;/h3&gt;
&lt;h4 id=&quot;第一章那一天&quot;&gt;第一章：「那一天」&lt;/h4&gt;
&lt;h5 id=&quot;1&quot;&gt;1&lt;/h5&gt;
&lt;p&gt;询问室的灯管有一根坏了，剩下的那根以一种不稳定的频率闪烁，像一个濒死的心电图。&lt;/p&gt;
&lt;p&gt;牛大力坐在金属椅子上，椅面冰凉，隔着牛仔裤都能感觉到。对面的Detective Kim把一杯纸杯咖啡推过来。咖啡闻起来像烧焦的轮胎。他没喝。&lt;/p&gt;
&lt;p&gt;“我需要你回忆那一天。”Kim说。她的声音没有感情，不是冷酷，更像是一个习惯了处理死亡的人特有的平静。“越详细越好。所有你能想起来的事。”&lt;/p&gt;
&lt;p&gt;牛大力看着那杯咖啡，棕色的液面映出一截变形的灯管。&lt;/p&gt;
&lt;p&gt;那一天。&lt;/p&gt;
&lt;p&gt;他闭了一下眼睛。早上七点五十分闹钟响，八点零三分出门，八点四十七分到公司，前提是101公路没有出车祸。101公路总是出车祸。同一个弯道，同一种追尾，就好像圣何塞的司机们共享同一套出错的自动驾驶程序。&lt;/p&gt;
&lt;p&gt;“从早上开始说吧。”Kim的笔悬在笔记本上。&lt;/p&gt;
&lt;p&gt;他深吸一口气。&lt;/p&gt;
&lt;p&gt;好吧。早上。&lt;/p&gt;
&lt;h5 id=&quot;2&quot;&gt;2&lt;/h5&gt;
&lt;p&gt;mala.ai的办公室在North San Jose的一栋三层商业楼里，和一家正畸诊所、一个跆拳道馆共享同一个停车场。楼的外墙是那种九十年代硅谷流行的灰白色，太阳一晒就像一块褪色的豆腐。&lt;/p&gt;
&lt;p&gt;不过走进去是另一个世界。CEO Derek Huang花了不少钱做装修——开放式工位、可升降办公桌、Herman Miller的椅子，墙上刷着品牌色的渐变蓝。茶水间有一台La Marzocco咖啡机、两台冰箱、一个零食架，零食架上永远有Kirkland的mixed nuts和那种日本小饼干。角落里有一间冥想室，门上贴着一张贴纸写着“recharge &amp;amp; refocus”，据牛大力所知，那间房的实际用途是午睡。&lt;/p&gt;
&lt;p&gt;每天早上的第一声响动是咖啡机的嗡鸣。九点零七分，准的——因为最早到办公室的永远是Andrei Volkov，公司的CFO。他是乌克兰人，五十来岁，灰白头发剃得很短，穿着永远是黑衬衫加黑裤子，像一个从约翰·勒卡雷的小说里走出来的角色。没人知道他的过去，也没人问。硅谷的规矩是你不问别人的过去，别人也不问你的。每个人都是从自己的前一段人生里逃出来的。&lt;/p&gt;
&lt;p&gt;Andrei按下咖啡机，机器发出第一声嗡鸣，就像这栋建筑的起床号。&lt;/p&gt;
&lt;p&gt;九点十五分，工程师们陆续到达。他们大多是中国人和印度人，穿着连帽衫和牛仔裤，背着同一款Northface或者Patagonia的双肩包，端着同一家Philz的外带杯。从停车场走进来的时候，他们看起来像是从同一条流水线上组装出来的。&lt;/p&gt;
&lt;p&gt;牛大力就是其中一个。&lt;/p&gt;
&lt;p&gt;九点半左右，产品VP李娜从电梯里出来，一手端着自己从家里带的保温杯——她从不喝公司的咖啡，说La Marzocco做出来的东西“像兑了水的焦油”——另一只手的手机贴着耳朵，用普通话在跟什么人说话，声音不大但语速很快，像在处理一件已经迟到了的事。她经过Andrei身边的时候，两个人交换了一个点头。公司里的高管们都有这种技能：用最少的肢体语言完成最多的社交义务。&lt;/p&gt;
&lt;p&gt;再晚一点，Ravi Krishnan推开玻璃门，背着一个塞得快炸开的双肩包，手里拎着一袋Trader Joe’s的东西。Ravi是三个月前从竞对跳过来的，IIT毕业，话特别多，那种你在茶水间站三分钟就能知道他昨晚看了什么YouTube视频、他妈妈又给他介绍了什么相亲对象的人。他看见牛大力就喊了一句：“Dali！你试过Trader Joe’s新出的那个mango sticky rice ice cream没有？改变人生的，我跟你说。”牛大力还没来得及回答，Ravi已经走远了。&lt;/p&gt;
&lt;h5 id=&quot;3&quot;&gt;3&lt;/h5&gt;
&lt;p&gt;“那天早上有什么特别的事吗？”Kim问。&lt;/p&gt;
&lt;p&gt;牛大力想了想。“有。Derek开了一个全体大会。”&lt;/p&gt;
&lt;p&gt;全体大会是Derek Huang最喜欢的仪式。每隔几周，他就会把全公司五十多个人召集到大厅里，站在一块移动白板前面，用一种TED演讲式的语调描绘公司的未来。&lt;/p&gt;
&lt;p&gt;Derek四十三岁，斯坦福MBA，在此之前创过两次业——第一次被收购，第二次死了。第三次是mala.ai。他长得不算帅，但有一种让人想跟着他走的魅力，就是那种你在机场酒吧遇到会主动搭话的人。他穿Allbirds，戴Apple Watch Ultra，说话的时候喜欢用手比划，好像在空气中画PPT。&lt;/p&gt;
&lt;p&gt;“我们的模型在三个benchmark上已经超过了OopenAI，”Derek站在白板前说，每说一句就在白板上画一个向上的箭头，“下一轮融资的conversation已经在进行了。我要你们每个人都知道——你们不是在打工，你们在making history。”&lt;/p&gt;
&lt;p&gt;牛大力坐在后排，看着Derek画了第四个箭头。他注意到Derek的Allbirds鞋底已经磨穿了一边。Making history的人大概没时间买新鞋。&lt;/p&gt;
&lt;p&gt;他旁边的Ravi在小声给他翻译Derek刚才引用的一个棒球比喻——“bottom of the ninth的意思是最后关头，就是说我们快赢了”——Ravi来美国两年了，对美国体育的理解还停留在板球的框架里。李娜站在第二排靠墙的位置，双臂交叉，脸上的表情是一种经过精确校准的中性——既不热情也不冷淡，像一个在董事会里待久了的人的默认设定。但牛大力注意到，当Derek说到“产品方向会有一些adjust”的时候，李娜的下巴微微收紧了一下。只有一下。Andrei站在最后面，靠着门框，双手插在裤兜里。他从来不坐下来听这种会。他的表情像是在听，又像是在想别的事。&lt;/p&gt;
&lt;p&gt;散会后，他在走廊里看到Derek拦住了一个实习生。实习生迟到了十分钟。Derek的脸从刚才全体大会上的光芒万丈切换成了一种他更熟悉的表情——不是愤怒，是比愤怒更冷的东西。他没听到Derek说了什么，但他看到实习生的手在发抖。&lt;/p&gt;
&lt;p&gt;李娜从旁边经过，看了一眼那个场景，脚步没停。她的脸上什么表情都没有，但牛大力觉得她走得比平时快了一点。Ravi凑过来，小声说：“噢，又来了。上次他也这样骂过那个做前端的实习生，那个人后来直接quit了。”&lt;/p&gt;
&lt;p&gt;凯文也走过来，压低声音补了一句：“Derek对迟到的人有一种私人恩怨。上辈子大概是德国火车调度员。”&lt;/p&gt;
&lt;p&gt;牛大力没笑。他突然想起一件事——最近几天，Derek看他的眼神也变了。不是实习生那种冷，是另一种东西。像是在看一个棋盘上即将被吃掉的棋子，但还没决定什么时候动手。&lt;/p&gt;
&lt;p&gt;他说不清那是什么。也许只是他想多了。&lt;/p&gt;
&lt;h5 id=&quot;4&quot;&gt;4&lt;/h5&gt;
&lt;p&gt;茶水间。下午三点。这是mala.ai的社交时刻——距离午饭足够远、距离下班足够近，人们端着咖啡聚在一起，假装在networking，其实是在拖延写代码。&lt;/p&gt;
&lt;p&gt;Ravi正站在零食架前，把一盒Kirkland的mixed nuts倒进自己的咖啡杯里——他坚持认为这样吃“更有效率”。李娜坐在角落的高脚凳上，对着笔记本电脑，耳机只戴了一只，像是在听什么会议录音，偶尔皱一下眉头在键盘上敲几个字。&lt;/p&gt;
&lt;p&gt;凯文靠在冰箱上，手里端着一杯茶水间自己做的拿铁，上面的拉花像一坨变形的cloud icon。话题不知道怎么就从Milpitas的麻辣烫开始了——可能是Ravi先提的，因为他昨天第一次吃了麻辣烫。&lt;/p&gt;
&lt;p&gt;“我跟你们说，”Ravi把坚果咖啡放在台面上，双手比划着，“那个地方叫Mala Town还是什么来着，我一进去就被辣哭了。literally流眼泪。但是停不下来。这个东西有毒吧？这不是食物，这是drug。”&lt;/p&gt;
&lt;p&gt;“你点的什么辣度？”牛大力问。&lt;/p&gt;
&lt;p&gt;“Medium。”&lt;/p&gt;
&lt;p&gt;凯文差点把拿铁喷出来。“你一个第一次吃麻辣烫的人点medium？那是给中国人点的medium。对你来说那是death。”&lt;/p&gt;
&lt;p&gt;“现在他告诉我，”Ravi说，摊开手，“why didn’t you warn me before I went?”&lt;/p&gt;
&lt;p&gt;“因为你没问我们啊，”牛大力说。&lt;/p&gt;
&lt;p&gt;“而且那家的麻辣烫也不算麻辣烫，”凯文说，搅了搅拿铁，“所有东西涮完浇一层芝麻酱。芝麻酱。那是火锅蘸料，不是麻辣烫配料。这就像你把番茄酱挤进意大利面里——技术上可以吃，道德上是犯罪。”&lt;/p&gt;
&lt;p&gt;“说到这个，”Ravi突然兴奋起来，“你们知道印度也有类似的东西吗？叫pani puri，就是一个小球，里面灌满了辣水，你一口塞进嘴里——”&lt;/p&gt;
&lt;p&gt;“Ravi，”李娜突然从笔记本后面抬起头，摘下一只耳机，“你们从三点开始就没停过。你们一个team的人都这么闲吗？”&lt;/p&gt;
&lt;p&gt;安静了一秒。然后Ravi说：“李娜姐，你要不要来一颗坚果？有益心脏健康。”&lt;/p&gt;
&lt;p&gt;李娜看了一眼他的咖啡杯。“你往咖啡里倒坚果？”&lt;/p&gt;
&lt;p&gt;“这是optimization——”&lt;/p&gt;
&lt;p&gt;“这是犯罪。”李娜说。她的脸上没什么表情，但语气里有一种干燥的幽默，像是不小心漏出来的。&lt;/p&gt;
&lt;p&gt;凯文和牛大力对视了一眼。李娜难得说笑话。或者说，她只是在陈述事实，只是事实本身恰好很好笑。&lt;/p&gt;
&lt;p&gt;“说真的，”李娜没有戴回耳机，“你们公司叫mala.ai，你们有没有想过这个名字有多讽刺？”&lt;/p&gt;
&lt;p&gt;牛大力没想到李娜会接这个话题。&lt;/p&gt;
&lt;p&gt;“一个ABC给公司起了个中国食物的名字，”李娜继续说，语气平淡，像在读季度财报，“投资人deck上写着’Where East Meets West in AI’。我们就是那个East。我们是调味料。”&lt;/p&gt;
&lt;p&gt;凯文举起咖啡杯。“李娜姐，我敬你这句话。”&lt;/p&gt;
&lt;p&gt;“我不需要你敬，”李娜说，“我需要你们产品上线日期别再推了。”&lt;/p&gt;
&lt;p&gt;Ravi笑得弯了腰。牛大力也笑了。连Andrei都在这个时候从走廊经过，端着他那杯永远是黑咖啡的黑咖啡，看了他们一眼。不是不赞同的那种看，是一种“我不理解你们在笑什么但我也无所谓”的看。&lt;/p&gt;
&lt;p&gt;“你们美国的麻辣烫不是麻辣烫，”牛大力说，他不知道为什么自己突然想说下去，“你在长沙吃的麻辣烫是什么样的？路边摊，塑料凳子，老板用一根长筷子在滚水里涮，烫好了撒一把葱花一勺辣椒油，四块钱一碗。连碗都是不锈钢的，烫手。那才叫麻辣烫。这里的，只能算是fanfiction。”&lt;/p&gt;
&lt;p&gt;“那我们也是fanfiction咯，”Ravi说，歪了歪头，“印度工程师、中国工程师、乌克兰CFO——全是美国对我们这些人的fanfiction。”&lt;/p&gt;
&lt;p&gt;所有人安静了一秒。Ravi有时候就会这样，在一堆废话中间突然说出一句让人想很久的东西。&lt;/p&gt;
&lt;p&gt;茶水间的灯光是暖黄色的，窗外的停车场在加州下午的阳光下白得刺眼。这是一个普通的下午。这是每一个下午。&lt;/p&gt;
&lt;h5 id=&quot;5&quot;&gt;5&lt;/h5&gt;
&lt;p&gt;牛大力说到这里停了一下。他意识到自己已经讲了好几分钟的麻辣烫和拉花，但Kim要听的是案件。&lt;/p&gt;
&lt;p&gt;“抱歉，”他说，“我跑题了。”&lt;/p&gt;
&lt;p&gt;Kim没抬头，笔还在动。“没关系。这些都有用。”她翻了一页笔记本。“那天下午在茶水间，都有谁？”&lt;/p&gt;
&lt;p&gt;牛大力想了想。“Ravi，李娜，凯文，我。Andrei路过了一下。来来去去的还有几个人进来倒过咖啡。”&lt;/p&gt;
&lt;p&gt;“你跟他们关系都怎么样？”&lt;/p&gt;
&lt;p&gt;“都不错。凯文是大学同学，认识最久。Ravi来了三个月，但他那个人很快就跟谁都熟了。李娜……李娜比较难说。她不太跟人交心，但人很好，那天她还难得跟我们开了个玩笑。Andrei就更不用说了，没人真的了解他。”&lt;/p&gt;
&lt;p&gt;Kim点了点头，在笔记本上记了什么。&lt;/p&gt;
&lt;h5 id=&quot;6&quot;&gt;6&lt;/h5&gt;
&lt;p&gt;Kim把笔放下了。“说说Derek Huang。你和他的关系怎么样？”&lt;/p&gt;
&lt;p&gt;牛大力想了想。“正常。就是老板和员工的关系。”&lt;/p&gt;
&lt;p&gt;“具体一点。”&lt;/p&gt;
&lt;p&gt;“他对我的工作评价不错。去年年底的performance review他给我打了Exceeds Expectations。但是……”&lt;/p&gt;
&lt;p&gt;“但是什么？”&lt;/p&gt;
&lt;p&gt;“最近几周他对我的态度变了。我说不清是什么——不是明显的敌意，更像是一种……距离感。以前我在走廊里遇到他，他会停下来问问项目进展，有时候还开玩笑。但最近他看到我就点个头，然后快步走开。有一次我在Micro Kitchen遇到他，他看着我——就那样看着我，看了大概三秒——然后什么都没说就走了。”&lt;/p&gt;
&lt;p&gt;“你觉得那是什么？”&lt;/p&gt;
&lt;p&gt;“我不知道。”这是实话。“后来我想过很多，但那时候我真的不知道。”&lt;/p&gt;
&lt;p&gt;他现在知道了。但那是后来的事。&lt;/p&gt;
&lt;h5 id=&quot;7&quot;&gt;7&lt;/h5&gt;
&lt;p&gt;窗外的光线暗了下来。询问室没有窗，但牛大力能感觉到外面的天在变暗——不知道为什么，被困在一个封闭空间里，你反而对外面的天色更加敏感。也许是本能。也许是因为你知道你不能出去。&lt;/p&gt;
&lt;p&gt;他给Kim讲了更多的事。讲了mala.ai的办公室布局（他甚至在纸上画了一张草图），讲了团队的结构，讲了他负责的那个核心模型。他没有讲模型训练数据的问题。不是故意隐瞒——是他当时还不知道那件事会如此重要。&lt;/p&gt;
&lt;p&gt;他讲了Derek的日常——早上九点半准时出现，总是最后到的那个管理层。讲了Derek怎么在Slack上用一种既casual又有压迫感的方式发消息——结尾永远是一个句号，不是感叹号也不是emoji，就是一个句号。一个句号比一百个感叹号更有威慑力。Ravi有一次说，每次收到Derek的Slack消息，他都要先做一次深呼吸再点开，“像拆一个可能是炸弹也可能是红包的快递”。&lt;/p&gt;
&lt;p&gt;他讲了李娜——她总是最后一个离开办公室的管理层，比Derek还晚。有人说她是工作狂，也有人说她是不想回家。他讲了Andrei——那个从不参加team lunch的CFO，午餐永远是一份从家里带的三明治，在自己的办公室里关着门吃。&lt;/p&gt;
&lt;p&gt;他讲了公司楼下的停车场，讲了对面街上的帐篷区。&lt;/p&gt;
&lt;p&gt;“帐篷区？”Kim抬了一下眉毛。&lt;/p&gt;
&lt;p&gt;“就在马路对面。大概十几顶帐篷。我们每天停好车走进公司的时候会经过那里。”&lt;/p&gt;
&lt;p&gt;“你有什么感觉？”&lt;/p&gt;
&lt;p&gt;牛大力沉默了一会儿。“你知道最讽刺的是什么吗？我们公司做的是AI，我们说我们在building the future。但我每天早上路过那些帐篷的时候，我能闻到——”他停了一下，“一种气味。不是臭，是一种很复杂的气味，像脏衣服和雨水和塑料布混在一起。每天早上我闻到那个气味，然后走进公司，闻到La Marzocco咖啡机的咖啡香。两种气味之间的距离是三十米。三十米。创造未来的人和被未来抛弃的人，共享同一个邮编。”&lt;/p&gt;
&lt;p&gt;Kim没说话。她在等他继续。&lt;/p&gt;
&lt;p&gt;“抱歉，”他说，“这和案件无关。”&lt;/p&gt;
&lt;p&gt;“你继续。”Kim说，“你能想到的所有事都有可能有关。”&lt;/p&gt;
&lt;h5 id=&quot;8&quot;&gt;8&lt;/h5&gt;
&lt;p&gt;“那一天，你有没有觉得有什么不对劲的地方？”Kim问。“任何不寻常的事。”&lt;/p&gt;
&lt;p&gt;牛大力想了很久。&lt;/p&gt;
&lt;p&gt;画面在他脑子里像一段损坏的录像带反复播放。Derek的Allbirds。全体大会上的箭头。实习生发抖的手。李娜收紧的下巴。Ravi的坚果咖啡。Andrei靠在门框上的轮廓。茶水间暖黄色的灯光。停车场刺眼的阳光。&lt;/p&gt;
&lt;p&gt;“没有。”他最终说。“那就是一个普通的日子。和之前的每一天一样。和之后的每一天一样。”&lt;/p&gt;
&lt;p&gt;他抬起头，看着Kim。&lt;/p&gt;
&lt;p&gt;“这就是问题所在，不是吗？”他说。“如果那天有什么不对劲的地方，我会记住的。但那天什么都没有。所以它就混进了其他所有的日子里。像一滴水掉进了海里。”&lt;/p&gt;
&lt;p&gt;Kim合上了笔记本。灯管还在闪。&lt;/p&gt;
&lt;p&gt;“今天先到这里。”她说。“明天我们继续。我需要你再仔细想想。尤其是那天晚上的事。”&lt;/p&gt;
&lt;p&gt;那天晚上。&lt;/p&gt;
&lt;p&gt;牛大力点了点头，站起来。金属椅子在地板上刮出一声尖响。&lt;/p&gt;
&lt;p&gt;他走出询问室，穿过走廊。走廊尽头有一扇窗，外面是圣何塞的夜景——101公路上的车灯像发光的血管，蜿蜒消失在远处。一切正常。一切都是每天的样子。&lt;/p&gt;
&lt;p&gt;但有一个人已经死了。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;第二章早安mala&quot;&gt;第二章：「早安，Mala」&lt;/h4&gt;
&lt;h5 id=&quot;9&quot;&gt;9&lt;/h5&gt;
&lt;p&gt;第二天晚上，Detective Kim把录音笔按开的时候，牛大力先听见的是自己呼吸的声音。&lt;/p&gt;
&lt;p&gt;“我们继续。”Kim说，“从早上开始。你说‘那天早上’。”&lt;/p&gt;
&lt;p&gt;那天早上。&lt;/p&gt;
&lt;p&gt;牛大力每次想到这里，脑子里先出现的都不是人，是一个纸杯。白底，绿色字母，Philz。杯壁上有一圈被手心捂出来的水汽。&lt;/p&gt;
&lt;h5 id=&quot;10&quot;&gt;10&lt;/h5&gt;
&lt;p&gt;早上八点四十七分，他刷卡进办公室，门禁“滴”了一声，像所有工作日一样干脆。&lt;/p&gt;
&lt;p&gt;凯文已经在工位上了，深蓝色连帽衫，袖口有一点起球，桌角放着四五杯Philz的外带杯，杯盖上贴着不同的便签。&lt;/p&gt;
&lt;p&gt;这倒不算什么新鲜事。凯文到得早，每隔几天就会在群里发一句“Philz run, 谁要+1”，然后帮大家带上来。今天Ravi在群里要了chai latte，李娜让带一杯冰美式，还有两个前端的工程师也跟了单。牛大力前一晚上睡得不好，早上通勤的时候在群里回了一句“薄荷拿铁”。&lt;/p&gt;
&lt;p&gt;“来，你的。”凯文从杯子堆里挑出一杯递过去。&lt;/p&gt;
&lt;p&gt;牛大力接过来，打开杯盖闻了闻。薄荷味很冲，像有人在清晨把一扇窗猛地推开。&lt;/p&gt;
&lt;p&gt;Ravi从外面冲进来，双肩包拉链都没拉好，一把抓走桌上写着他名字的那杯：“Kevin你是天使。如果你是一个app我给你五星。”他又从自己的双肩包里掏出一个塑料袋，“这是我妈寄过来的masala chips，你们一人一包，不要跟我客气。”&lt;/p&gt;
&lt;p&gt;他往牛大力桌上扔了一包，又往凯文桌上扔了一包，然后拎着剩下的朝李娜的方向走去。&lt;/p&gt;
&lt;p&gt;凯文低头看了一眼那包chips，笑了：“Ravi的妈妈一定觉得他在喂一整个村子。”&lt;/p&gt;
&lt;p&gt;“今天有什么事？”牛大力问。&lt;/p&gt;
&lt;p&gt;“没事。”凯文耸耸肩，“开会多。省得你十点前死机。”&lt;/p&gt;
&lt;h5 id=&quot;11&quot;&gt;11&lt;/h5&gt;
&lt;p&gt;mala.ai的早晨永远是工业化的。&lt;/p&gt;
&lt;p&gt;升降桌缓慢上升的电机声，机械键盘像雨点一样落在木桌板上，显示器背光把每张脸照成同一种白。Ravi一边插电源一边讲他昨晚在Reddit上看到的阴谋论，Andrei路过茶水间，给自己的黑咖啡加第二次浓缩。李娜从会议室里走出来，手机贴着耳朵，中文和英文切换得没有缝，像在双语操作系统里开了两个线程。&lt;/p&gt;
&lt;p&gt;牛大力坐下，打开Slack。未读消息四十三条。最上面是Derek昨晚十一点发的提醒：&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Need final numbers by EOD Thursday.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;句号依然在。Derek所有消息都带句号。好像每句话都已经定案。&lt;/p&gt;
&lt;h5 id=&quot;12&quot;&gt;12&lt;/h5&gt;
&lt;p&gt;十点零五分，全员会。&lt;/p&gt;
&lt;p&gt;Derek站在大厅白板前面，画了三个箭头，讲了四次“execution”，两次“category-defining”，一次“once-in-a-generation opportunity”。&lt;/p&gt;
&lt;p&gt;“下周和两家顶级基金进深聊，”他说，“我们离breakout就差一个漂亮的数据点。”&lt;/p&gt;
&lt;p&gt;掌声响起来，稀稀拉拉。工程师们的掌声都像在跑单元测试，目标是“通过”，不是“动情”。&lt;/p&gt;
&lt;p&gt;牛大力坐在后排，盯着Derek鞋边那道磨损。那双Allbirds左脚外侧磨得更厉害。一个总在往前冲的人，重心会偏向同一边。&lt;/p&gt;
&lt;p&gt;会议结束时，Derek的目光在他脸上停了两秒。就两秒，不长，但足够让人不舒服。那不是“你做得不错”的目光，也不是“你给我麻烦了”的目光。更像是一个人站在超市货架前，看着某件东西，判断它还能不能继续用。&lt;/p&gt;
&lt;h5 id=&quot;13&quot;&gt;13&lt;/h5&gt;
&lt;p&gt;午饭去的是公司后面那家越南粉店，门口写着&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cash preferred&lt;/code&gt;，玻璃门上贴着一张褪色的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NOW HIRING&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;他们六个人挤在一张四人桌，桌子摇摇晃晃，像硅谷所有早期创业公司的组织结构。&lt;/p&gt;
&lt;p&gt;Ravi先开炮：“你们美国人这个小费系统太奇怪了。菜单价格不是价格，真正价格藏在后面。你们用guilt定价。”&lt;/p&gt;
&lt;p&gt;凯文说：“15%是礼貌，18%是正常，20%是你想下辈子投胎当好人。”&lt;/p&gt;
&lt;p&gt;“那0%呢？”Ravi问。&lt;/p&gt;
&lt;p&gt;“0%是你还没走出门就被老板娘拿拖鞋追出来。”&lt;/p&gt;
&lt;p&gt;全桌笑了。&lt;/p&gt;
&lt;p&gt;牛大力看着账单计算器上的数字跳来跳去，说：“我每次都给20%，不是因为我想给。是因为我怕我算错，然后被定义成‘那个中国工程师’。”&lt;/p&gt;
&lt;p&gt;李娜把筷子放下，淡淡地说：“欢迎来到美国。这里一切都可以量化，除了体面。体面靠自觉充值。”&lt;/p&gt;
&lt;p&gt;Andrei抬眼看了她一下，没接话，继续喝汤。&lt;/p&gt;
&lt;h5 id=&quot;14&quot;&gt;14&lt;/h5&gt;
&lt;p&gt;回程路上，太阳亮得过分。停车场对面帐篷区的蓝色篷布在风里拍打，像一排旧旗子。&lt;/p&gt;
&lt;p&gt;Ravi还在讲房租：“我昨天看Zillow，Santa Clara一个一居室要三千二。三千二！这个价格在班加罗尔我能住进一个有泳池和健身房的高层。”&lt;/p&gt;
&lt;p&gt;凯文说：“在这里三千二你住进的是‘地理位置优越’。翻译一下就是‘厨房和床之间只有一步’。”&lt;/p&gt;
&lt;p&gt;“你们至少还有H1B，”Ravi说，“我还在F1 OPT，四月份抽签，求God保佑我能中。”&lt;/p&gt;
&lt;p&gt;牛大力没说话。Ravi一提签证，他就忍不住打开了手机上的case tracker。页面转了两秒，跳出来的还是那行字：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Case Was Received&lt;/code&gt;。两年了，一直是这行字。每次看都像在读一句没有主语的判决。&lt;/p&gt;
&lt;p&gt;他们走进公司，自动门关上，外面的风和味道一起被隔绝。里面是咖啡、空调、显示器。未来总有一股很干净的气味。&lt;/p&gt;
&lt;h5 id=&quot;15&quot;&gt;15&lt;/h5&gt;
&lt;p&gt;下午四点二十三分，第一条异常消息出现。&lt;/p&gt;
&lt;p&gt;Ravi在工程频道里发了一个链接：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new vLLM CVE dropped&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;两分钟后，另一个人贴了PoC。三分钟后，SRE在群里问&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;are we exposed in prod?&lt;/code&gt;。四点三十一分，Derek出现：&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;All engineering hands on deck. Assess impact NOW.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;这次没有句号。&lt;/p&gt;
&lt;p&gt;办公室的空气在十秒内变了。有人把外放音乐关掉，有人冲向白板写服务依赖，有人开始翻锁定版本和镜像哈希。连茶水间咖啡机都停了，因为没人再去按它。
Ravi第一个跑到白板前面，拿起马克笔画了一张服务依赖图，速度快得像在做限时考试。李娜从会议室里出来，耳机摘了，手机收了，走到工程区问：“影响范围出来了吗？我需要给客户那边发个预警。”Andrei不知道什么时候也出现了，站在Ravi身后看那张依赖图，一言不发，但偶尔会伸手点一下某个节点，意思是“这里也要查”。
凯文把椅子滑到牛大力旁边，语速比平时快一点：“你看推理服务那层，我去查我们fork的分支和上游差异。先别慌，先算暴露面。”&lt;/p&gt;
&lt;p&gt;牛大力点头，手已经在键盘上了。&lt;/p&gt;
&lt;h5 id=&quot;16&quot;&gt;16&lt;/h5&gt;
&lt;p&gt;傍晚六点十五分，Derek从会议室出来，脸色不好看。&lt;/p&gt;
&lt;p&gt;“今晚所有人都别走。”他说，“我要凌晨前看到结论。不是明天。是今晚。”&lt;/p&gt;
&lt;p&gt;李娜问：“如果要热修，产品节奏要不要调整？”&lt;/p&gt;
&lt;p&gt;Derek看都没看她：“现在不是讨论节奏的时候。”&lt;/p&gt;
&lt;p&gt;这句话像一记干脆的耳光。李娜下巴收紧，没再说话。她转身回了工位，打开一个Google Doc开始写客户沟通的话术模版，键盘敲得很用力，像在把那记耳光还回去。&lt;/p&gt;
&lt;p&gt;到了七点前后，饥饿开始蔓延。Ravi第一个投降：“我要死了，谁去买吃的？”他翻了翻手机上的DoorDash，嫌配送费太贵，又关掉。李娜说她车里有几根能量棒，去拿了一把回来，往桌上一撒：“先顶着。”Andrei从自己办公室里拿出一袋超市买的杏仁，放在公共区，没说话。&lt;/p&gt;
&lt;p&gt;凯文起身抓了抓头发：“我去买点吃的吧，反正我车在楼下。你们要什么？”&lt;/p&gt;
&lt;p&gt;Ravi喊了一句“三明治，什么都行”。另一个前端工程师说“饭团”。牛大力说“都行”。&lt;/p&gt;
&lt;p&gt;“好，我尽快回来。”&lt;/p&gt;
&lt;p&gt;凯文拿起车钥匙就走了。&lt;/p&gt;
&lt;p&gt;当时这件事没有任何特别。加班夜里，总得有人出去跑一趟。只是在后来，牛大力总会记起这句“我尽快回来”，像一颗没有拧紧的螺丝，安静地卡在记忆里。&lt;/p&gt;
&lt;h5 id=&quot;17&quot;&gt;17&lt;/h5&gt;
&lt;p&gt;后来的记忆变得不那么清晰了。不是忘了，是太多东西堆在一起，像同一个文件夹里塞了太多截图，缩略图全部缩成了一团。&lt;/p&gt;
&lt;p&gt;他记得补丁改了很久。有人在白板上画了三遍架构图又擦掉。Ravi在某个时刻瘫在椅子上仰头看天花板，说了句“如果这就是AI革命，那我建议革命明天再来”。有人笑了两声，很快又安静。李娜不知道什么时候泡了一壶茶放在公共桌上，旁边摆了一排纸杯，谁渴了自己倒。Andrei回了一趟自己的办公室，出来的时候换了一双拖鞋——他在公司放了一双——大概是做好了通宵的准备。&lt;/p&gt;
&lt;p&gt;凯文回来了，手里拎着两大袋便利店的东西。他什么时候回来的？牛大力不确定。好像是八点多，也可能是九点。Ravi扑过去翻袋子，找到自己的三明治，撕开包装狼吞虎咽。凯文把饭团递给那个前端工程师，自己坐回了牛大力对面，深蓝连帽衫在冷白灯下看起来几乎是黑色的，开始帮他看一段推理链路的异常日志。&lt;/p&gt;
&lt;p&gt;补丁的事慢慢稳定下来之后，凯文突然合上笔记本说：“走，出去吃个拉面。盯屏幕太久了。”&lt;/p&gt;
&lt;p&gt;他们去了公司附近新开的那家拉面店。店里很空，只有他们两个客人，后厨传来抽油烟机的轰鸣和日语的低声说笑。凯文点了浓汤豚骨，他要了酱油拉面。&lt;/p&gt;
&lt;p&gt;面上来之前，凯文看着他说：“你今天状态不对。”&lt;/p&gt;
&lt;p&gt;“嗯？”&lt;/p&gt;
&lt;p&gt;“太安静了。比平时安静。”&lt;/p&gt;
&lt;p&gt;牛大力拿起筷子戳了戳面前的小碟蘸料。“可能就是累。”&lt;/p&gt;
&lt;p&gt;凯文没追问。他们沉默地吃完了拉面。&lt;/p&gt;
&lt;p&gt;回到公司以后继续写代码。pair programming，凯文写一段他review，交替进行，像两个人合下一盘很慢的棋。这种节奏他很熟悉——大学的时候他们就这样写作业，一个人敲一个人看，谁先发现bug谁请下一顿奶茶。安静的，有效率的，不需要说话的那种默契。&lt;/p&gt;
&lt;p&gt;窗外停车场的灯光照进来，把地板切成一条一条的明暗。&lt;/p&gt;
&lt;h5 id=&quot;18&quot;&gt;18&lt;/h5&gt;
&lt;p&gt;凌晨的时候，人终于开始散了。Ravi第一个倒下，直接躺在休息区的沙发上，用自己的Patagonia外套盖着脸。李娜叫了一辆Uber，走之前把茶壶洗了放回柜子里。Andrei不知道什么时候已经走了，没人看见他离开——他总是这样，像一个不会触发门铃的人。几个工程师打车回家，有人回工位补最后一封邮件。&lt;/p&gt;
&lt;p&gt;牛大力收电脑的时候，看见凯文还在发Slack消息，内容是例行进度更新，后面跟了个平时常用的emoji。看起来一切都正常，正常得像模板。&lt;/p&gt;
&lt;p&gt;他走到门口，回头看了一眼办公室。灯还亮着一半，像城市里任何一个加班中的楼层。&lt;/p&gt;
&lt;p&gt;“那天晚上就是这样。”牛大力对Kim说。&lt;/p&gt;
&lt;p&gt;Kim翻了翻笔记，没有抬头。“你确定？就这些？”&lt;/p&gt;
&lt;p&gt;“就这些。一个普通的加班夜。”&lt;/p&gt;
&lt;p&gt;Kim把笔记本合上，说了句“好，今天先到这里”。&lt;/p&gt;
&lt;p&gt;牛大力站起来，金属椅子在地板上刮出一声尖响。走出询问室的时候，他总觉得有什么地方不太对。像一段代码通过了所有测试，lint也没有报错，但你就是觉得哪里不干净。你说不出是哪一行。你只是觉得。&lt;/p&gt;
&lt;p&gt;在硅谷，很多日子都像重复提交的代码。你以为自己在写新版本，其实只是在覆盖旧文件。而最危险的bug，往往藏在你以为没改过的那几行里。&lt;/p&gt;
&lt;h4 id=&quot;第三章顶层的沉默&quot;&gt;第三章：「顶层的沉默」&lt;/h4&gt;
&lt;h5 id=&quot;19&quot;&gt;19&lt;/h5&gt;
&lt;p&gt;第三天晚上，Kim又把录音笔放在桌上，红灯亮起来。&lt;/p&gt;
&lt;p&gt;“我们把时间线往后推。”她说，“发现尸体之后，你当时在哪儿？”&lt;/p&gt;
&lt;p&gt;牛大力盯着那颗红点看了两秒。&lt;/p&gt;
&lt;p&gt;“公司。”他说，“和凯文一起。”&lt;/p&gt;
&lt;p&gt;Kim点头，像是早就知道答案。&lt;/p&gt;
&lt;p&gt;“从你接到电话开始说。”&lt;/p&gt;
&lt;h5 id=&quot;20&quot;&gt;20&lt;/h5&gt;
&lt;p&gt;电话是晚上十点多打来的。号码他不认识。&lt;/p&gt;
&lt;p&gt;“Is this Dali Niu? This is San Jose Police Department. We need you to come to your office immediately.”&lt;/p&gt;
&lt;p&gt;那一瞬间他脑子是空的。不是恐惧，是一种系统卡死式的空白，像你在终端里敲了一条命令，屏幕只回你一个转个不停的光标。&lt;/p&gt;
&lt;p&gt;“发生什么了？”&lt;/p&gt;
&lt;p&gt;“A death investigation, sir.”&lt;/p&gt;
&lt;p&gt;他站在公寓厨房里，手还扶着水槽边，指尖有点发麻。灶台上是一锅刚煮开的挂面，蒸汽往上顶，把油烟机下面那盏灯熏出一圈白雾。&lt;/p&gt;
&lt;p&gt;他把火关了，外套也没换，抓起车钥匙就出门。&lt;/p&gt;
&lt;p&gt;101公路夜里照样堵，只是不再是白天那种硬塞，而是一段一段地挪。车流像低帧率视频，卡一下，走两米，再卡一下。导航显示二十三分钟，他开了四十分钟。&lt;/p&gt;
&lt;p&gt;到公司楼下的时候，停车场已经停了两辆警车。蓝红警灯在墙面上轮流刷过，像廉价夜店的灯光，但没有音乐。&lt;/p&gt;
&lt;h5 id=&quot;21&quot;&gt;21&lt;/h5&gt;
&lt;p&gt;大楼一层的玻璃门开着，保安站在门口，脸色比平时白。&lt;/p&gt;
&lt;p&gt;“上面，顶楼会议室。”保安说，“你们CEO……在里面。”&lt;/p&gt;
&lt;p&gt;牛大力抬头看了一眼楼梯间。那条往上的楼梯平时很少有人走，灯管偏暗，拐角处的阴影显得很深。&lt;/p&gt;
&lt;p&gt;电梯门开的时候，他先闻到一股过冷空调和清洁剂混在一起的味道。警戒线把顶层走廊拦成两截。会议室门开着，门口站着两名法证人员，白色连体防护服在灯下发蓝。&lt;/p&gt;
&lt;p&gt;再往里一点，两个穿制服的巡警靠在打印机旁边低声聊天，声音压得很低，但在空走廊里反而清楚。&lt;/p&gt;
&lt;p&gt;“你看《三体》了吗？”一个问。&lt;/p&gt;
&lt;p&gt;“小说看了，Netflix那个我看了三集就关了，”另一个说，“中国科幻现在确实猛，但那个改编……有点浪费。”&lt;/p&gt;
&lt;p&gt;“对吧，我就说。你不能把所有角色都拍成会说俏皮话的美剧人设。”&lt;/p&gt;
&lt;p&gt;说完这句，两人又立刻收声，转头看向警戒线里。&lt;/p&gt;
&lt;p&gt;李娜靠在走廊尽头的墙边，双臂抱在胸前，手机攥得很紧，屏幕亮了又灭。Ravi坐在地上，后背贴着墙，眼神发直，像刚跑完一场半马却不知道终点在哪。Andrei站在窗边，手插在裤兜里，脸上没有表情，像任何一次季度财报会前的样子。&lt;/p&gt;
&lt;p&gt;凯文在离他两步远的地方，先看见他，走过来拍了拍他肩膀。&lt;/p&gt;
&lt;p&gt;“你没事吧？”凯文问。&lt;/p&gt;
&lt;p&gt;牛大力摇头。其实他不知道自己有没有事。&lt;/p&gt;
&lt;p&gt;“到底怎么回事？”&lt;/p&gt;
&lt;p&gt;“行政助理晚上一直联系不上Derek，”凯文压低声音说，“电话不接，Slack不回。她让保安上来看，门打开就……”&lt;/p&gt;
&lt;p&gt;他停了一下，又补了一句：“她说下午还收到过Derek发的短信，让她把周四的会都取消，说要在家准备董事会。”&lt;/p&gt;
&lt;p&gt;他没把后半句说完。&lt;/p&gt;
&lt;h5 id=&quot;22&quot;&gt;22&lt;/h5&gt;
&lt;p&gt;Detective Kim就是在那时出现的。她戴着一次性手套，从警戒线里走出来，手里拿着一个薄本子。&lt;/p&gt;
&lt;p&gt;“Dali Niu？”&lt;/p&gt;
&lt;p&gt;“是我。”&lt;/p&gt;
&lt;p&gt;“我需要你和其他人都留在现场。我们要逐个做初步问询。”&lt;/p&gt;
&lt;p&gt;她看人的方式很特别，不凶，也不温和。像在读一段你以为写得很清楚、其实全是歧义的代码。&lt;/p&gt;
&lt;p&gt;先被叫走的是行政助理，接着是保安，再是李娜。Ravi进去之前小声骂了句“what the hell”，像在骂一个突然崩掉的线上服务。Andrei进去出来都很快，前后不超过七分钟。&lt;/p&gt;
&lt;p&gt;轮到牛大力时，Kim的第一个问题不是“你最后一次见到死者是什么时候”。&lt;/p&gt;
&lt;p&gt;她问的是：&lt;/p&gt;
&lt;p&gt;“今晚联系不上你们CEO的时候，为什么没人第一时间觉得不对？”&lt;/p&gt;
&lt;p&gt;牛大力愣了一下。“我们以为他在家办公。”&lt;/p&gt;
&lt;p&gt;“为什么会这么以为？”&lt;/p&gt;
&lt;p&gt;“Slack状态。”他说，“下午就改成了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;🏠 Working from home — board prep day&lt;/code&gt;。他还在#general发了消息，说今天专心准备董事会材料，urgent的再找他。”&lt;/p&gt;
&lt;p&gt;Kim翻了翻本子，又问：“所以你们所有人都默认，他在家，在线，只是没回消息？”&lt;/p&gt;
&lt;p&gt;“对。”&lt;/p&gt;
&lt;p&gt;这个“对”出口的时候，牛大力自己都觉得荒唐。一个几十人的公司，从傍晚到深夜都没人见过CEO本人，却可以靠一个状态图标维持秩序运行。&lt;/p&gt;
&lt;p&gt;在硅谷，在线状态有时候比真人更像真人。&lt;/p&gt;
&lt;h5 id=&quot;23&quot;&gt;23&lt;/h5&gt;
&lt;p&gt;问询结束已经过了午夜。会议室门口的灯还亮着，法证人员进进出出，提着黑色器材箱。&lt;/p&gt;
&lt;p&gt;Kim让他们在大厅等，随时准备补充口供。&lt;/p&gt;
&lt;p&gt;Ravi站在咖啡机前，按了两次都没按出东西，才想起来机器晚上会自动关机。他低声说了句“连咖啡都没了”，听起来像一句非常不合时宜的遗言。&lt;/p&gt;
&lt;p&gt;他转过头又嘟囔了一句：“昨天也熬到半夜，今天又来这一出……我脑子已经分不清是哪天了。”&lt;/p&gt;
&lt;p&gt;李娜在给谁发消息，打字速度比平时快一倍，删掉重写又删掉。Andrei去自动贩卖机买了一瓶常温水，拧开喝了两口，剩下半瓶一直攥在手里。&lt;/p&gt;
&lt;p&gt;凯文拉了把椅子坐到牛大力旁边。&lt;/p&gt;
&lt;p&gt;牛大力这时才注意到，凯文还是那件深蓝连帽衫，袖口那点起球的位置都没变。硅谷工程师连着两天穿同一件衣服很常见，但那一秒他还是生出了一点说不清的熟悉感。&lt;/p&gt;
&lt;p&gt;“你脸色很差。”他说，“先坐着，别硬撑。”&lt;/p&gt;
&lt;p&gt;牛大力点点头，坐下去，才发现自己腿在抖。&lt;/p&gt;
&lt;p&gt;“你今天什么时候和我在一起的？”他忽然问。&lt;/p&gt;
&lt;p&gt;凯文看了他一眼，像是没想到他会问这个。&lt;/p&gt;
&lt;p&gt;“下班后一直在一起啊。你忘了？我们六点多就在那边pair，后来还去吃了拉面，回来继续改日志。”&lt;/p&gt;
&lt;p&gt;牛大力“嗯”了一声。他当然记得。至少他以为自己记得。&lt;/p&gt;
&lt;h5 id=&quot;24&quot;&gt;24&lt;/h5&gt;
&lt;p&gt;凌晨一点半左右，Kim把他们重新叫到会议室外的小桌前，做最后一轮时间线确认。&lt;/p&gt;
&lt;p&gt;她说得很直接：“今晚每个人都给我一个可验证的不在场证明。几点到几点，和谁在一起，做了什么，谁能作证。”&lt;/p&gt;
&lt;p&gt;“另外，”她抬头扫了一圈，“我们会调门禁、Slack记录和代码提交时间。各位今晚先不要删消息，也不要改状态。”&lt;/p&gt;
&lt;p&gt;李娜先说了自己的行程，精确到会议和电话时间。Andrei报了一串几乎没有情绪的时间节点，像在念一份审计流水。Ravi卡壳了两次，最后靠Slack和Git提交时间把自己拼完整。&lt;/p&gt;
&lt;p&gt;凯文的说法最完整，也最容易核对。&lt;/p&gt;
&lt;p&gt;“我和Dali从晚上六点到十点基本都在一起，”他说，“中间出去吃了四十分钟拉面。回公司后继续pair。我们的提交记录能对上，门禁也能查到。”&lt;/p&gt;
&lt;p&gt;Kim把目光转向牛大力：“他说的准确吗？”&lt;/p&gt;
&lt;p&gt;“准确。”牛大力说。&lt;/p&gt;
&lt;p&gt;她点头，记下。&lt;/p&gt;
&lt;p&gt;那一刻，牛大力甚至有一点荒谬的安心。像在一团噪音里终于抓到一根稳定的线：至少有一个人的时间是清楚的，至少有一段记忆是可以被证实的。&lt;/p&gt;
&lt;p&gt;后来他才知道，安心有时候也会误导人。&lt;/p&gt;
&lt;p&gt;他和凯文一起走出公司大门时，凌晨的风很冷。停车场里警灯还在闪，蓝一下，红一下，像一个永远不结束的光标。&lt;/p&gt;
&lt;p&gt;“回去睡一觉吧。”凯文说。&lt;/p&gt;
&lt;p&gt;牛大力点头。&lt;/p&gt;
&lt;p&gt;那段时间在他的记忆里，一直有一个固定的名字。很久以后他才发现，记忆先给出的标签，未必总是最接近真相。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;第四章每个人的裂缝&quot;&gt;第四章：「每个人的裂缝」&lt;/h4&gt;
&lt;h5 id=&quot;25&quot;&gt;25&lt;/h5&gt;
&lt;p&gt;第四天，Kim没再让牛大力“从头说起”。&lt;/p&gt;
&lt;p&gt;她把一叠打印材料放在桌上，指尖在最上面那页轻轻敲了一下。&lt;/p&gt;
&lt;p&gt;“今天我们不聊感觉，”她说，“聊动机。一个一个来。”&lt;/p&gt;
&lt;p&gt;牛大力点头。他知道这一轮会很难。&lt;/p&gt;
&lt;p&gt;凶案之后，公司里每个人都像刚刚升级过一次防火墙。说话更慢，邮件更短，Slack里emoji突然变少。茶水间还有咖啡香，但人们端着杯子站在一起时，先看的是彼此的眼睛，确认对方值不值得说下一句。&lt;/p&gt;
&lt;h5 id=&quot;26&quot;&gt;26&lt;/h5&gt;
&lt;p&gt;第一个是李娜。&lt;/p&gt;
&lt;p&gt;Kim把一份截图推到桌子中间。邮件草稿，收件人是董事会，标题是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Re: Product Leadership Change&lt;/code&gt;。草稿里有一句话被高亮：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transition in product leadership after the board meeting&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;“你知道这封草稿吗？”Kim问。&lt;/p&gt;
&lt;p&gt;李娜盯着那行字看了两秒，嘴角绷得很直。“不知道。”&lt;/p&gt;
&lt;p&gt;“你和Derek最近关系很紧张。”&lt;/p&gt;
&lt;p&gt;“我和他一直紧张，”李娜说，“我们在战略上有分歧，不是新闻。”&lt;/p&gt;
&lt;p&gt;“如果董事会后你被降职呢？”&lt;/p&gt;
&lt;p&gt;李娜笑了一下，笑意很薄。“Detective，我在硅谷做了十年。今天title在，明天title没了，这种事我见得比你见尸体还多。”&lt;/p&gt;
&lt;p&gt;她停了一下，声音压低：“但我不会因为一封我没见过的草稿去杀人。”&lt;/p&gt;
&lt;p&gt;牛大力后来回想，那一刻李娜脸上同时有两种表情：愤怒和恐惧。愤怒是给Kim的，恐惧是给那封邮件的。&lt;/p&gt;
&lt;h5 id=&quot;27&quot;&gt;27&lt;/h5&gt;
&lt;p&gt;第二个是Andrei。&lt;/p&gt;
&lt;p&gt;Kim给他看的是一段楼梯间监控，画面颗粒粗得像上个世纪的录像带。一个模糊身影穿着深灰色外套，从顶层往下走。&lt;/p&gt;
&lt;p&gt;“这件外套像你的。”Kim说。&lt;/p&gt;
&lt;p&gt;Andrei看完，面无表情。“像，不代表是。”&lt;/p&gt;
&lt;p&gt;“你有一件类似的深灰大衣。”&lt;/p&gt;
&lt;p&gt;“丢了。两周前。”&lt;/p&gt;
&lt;p&gt;“有报失记录吗？”&lt;/p&gt;
&lt;p&gt;“没有。”&lt;/p&gt;
&lt;p&gt;Kim把笔放下。那一下很轻，但房间里所有人都听见了。&lt;/p&gt;
&lt;p&gt;Andrei继续说：“你们想要一个简单故事：有财务问题的CFO，深夜出现在楼梯间。很好讲。但现实不是PPT。”&lt;/p&gt;
&lt;p&gt;他说完就沉默，像把门从里面锁上。&lt;/p&gt;
&lt;h5 id=&quot;28&quot;&gt;28&lt;/h5&gt;
&lt;p&gt;第三个是Ravi。&lt;/p&gt;
&lt;p&gt;这次是数字取证。Kim把一张内部搜索日志递过去：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Derek Huang stock options vesting schedule&lt;/code&gt;，账号名是Ravi。&lt;/p&gt;
&lt;p&gt;“这不是我搜的。”Ravi第一反应就是摇头，摇得很用力，“I swear to god，这真的不是我。”&lt;/p&gt;
&lt;p&gt;“记录显示是你的工位设备，你的账号，周三下午。”&lt;/p&gt;
&lt;p&gt;“那时候我在修bug！我可能去过厕所，或者去拿咖啡，但我没搜这个。”&lt;/p&gt;
&lt;p&gt;Kim没接这句话，只问：“你为什么会关心他vesting？”&lt;/p&gt;
&lt;p&gt;“我不关心！”Ravi声音抬高了半格，又自己压下去，“我连自己401(k)都懒得看。”&lt;/p&gt;
&lt;p&gt;他说完那句，抬头看牛大力，眼神像在问：你信我吗？&lt;/p&gt;
&lt;p&gt;牛大力没法立刻回答。不是不想，是他突然发现自己对所有人的记忆都开始失真。&lt;/p&gt;
&lt;h5 id=&quot;29&quot;&gt;29&lt;/h5&gt;
&lt;p&gt;第四个轮到牛大力自己。&lt;/p&gt;
&lt;p&gt;Kim把笔记本转了个方向，像是故意提醒他：你不是旁听席，你也在名单里。&lt;/p&gt;
&lt;p&gt;“你和Derek最后一次一对一谈话是什么时候？”&lt;/p&gt;
&lt;p&gt;“案发前一周。”牛大力说。&lt;/p&gt;
&lt;p&gt;“谈了什么？”&lt;/p&gt;
&lt;p&gt;“项目，董事会，和……一些方向问题。”&lt;/p&gt;
&lt;p&gt;“方向问题，还是责任切割？”Kim盯着他，“我们看到你负责的模型有合规灰区。你有没有担心，Derek会把问题推到你身上？”&lt;/p&gt;
&lt;p&gt;牛大力喉咙发紧，没立刻回答。&lt;/p&gt;
&lt;p&gt;Kim继续问：“如果你觉得自己会被开除、被起诉、签证受影响——这是不是动机？”&lt;/p&gt;
&lt;p&gt;这句话落下来的时候，房间安静得能听到空调风口的嗡鸣。&lt;/p&gt;
&lt;p&gt;“我没有杀他。”牛大力说。&lt;/p&gt;
&lt;p&gt;“我问的不是结论，”Kim说，“我问的是动机是否存在。”&lt;/p&gt;
&lt;p&gt;牛大力看着桌上的木纹，一道一道，像程序里的缩进线。过了几秒，他才说：“存在。压力一直都在。但存在动机，不等于会去做那件事。”&lt;/p&gt;
&lt;p&gt;Kim点头，把这句记了下来。&lt;/p&gt;
&lt;p&gt;“还有时间线。”她说，“周四晚上六点到十点，你和谁在一起？”&lt;/p&gt;
&lt;p&gt;“凯文。”&lt;/p&gt;
&lt;p&gt;“持续在一起？”&lt;/p&gt;
&lt;p&gt;“中间出去吃了拉面，其他时间基本都在一起。”&lt;/p&gt;
&lt;p&gt;Kim把笔帽扣上，又打开，像在想什么。&lt;/p&gt;
&lt;p&gt;“好。你的设备也会做完整取证。手机、公司电脑、门禁、提交记录，都会核。”&lt;/p&gt;
&lt;p&gt;牛大力点了点头。那一刻他第一次真正理解了“嫌疑人”这个词——不是一个标签，是一种被系统性拆开的感觉。&lt;/p&gt;
&lt;h5 id=&quot;30&quot;&gt;30&lt;/h5&gt;
&lt;p&gt;轮到凯文时，问询节奏明显快了一点。Kim的问题仍然直接，但语气比前面更平。&lt;/p&gt;
&lt;p&gt;“你周四下午三点刷过顶楼门禁。”Kim说。&lt;/p&gt;
&lt;p&gt;“对，”凯文点头，“我去拿Derek之前答应借我的一本书。门锁着，我没进去，站了半分钟就下来了。”&lt;/p&gt;
&lt;p&gt;“有人听到你周一和Derek在走廊争执。”&lt;/p&gt;
&lt;p&gt;“技术路线吵架，API接口怎么拆。我们经常吵。”&lt;/p&gt;
&lt;p&gt;“你周三深夜11点发过一封CVE相关邮件。”&lt;/p&gt;
&lt;p&gt;“那天都在加班，发封总结很正常。”&lt;/p&gt;
&lt;p&gt;Kim把三份打印页并排摆开：门禁、Git提交、Slack时间戳。&lt;/p&gt;
&lt;p&gt;“18:12到20:03，你和Dali在同一分支有交替提交。20:11到20:49，这段空白在做什么？”&lt;/p&gt;
&lt;p&gt;“去吃拉面。”凯文说。&lt;/p&gt;
&lt;p&gt;“谁提议的？”&lt;/p&gt;
&lt;p&gt;“我。”&lt;/p&gt;
&lt;p&gt;“回来后呢？”&lt;/p&gt;
&lt;p&gt;“继续pair，到十点左右。”&lt;/p&gt;
&lt;p&gt;Kim又问了两条细节：拉面店位置、回程路线。凯文都答上来了。&lt;/p&gt;
&lt;p&gt;她把那几页叠回去，点了点头，示意下一位。&lt;/p&gt;
&lt;p&gt;牛大力坐在旁边，看着表格里一串一串时间，忽然觉得它们像自动生成的日志：格式正确，语法正确，但没有任何温度。&lt;/p&gt;
&lt;h5 id=&quot;31&quot;&gt;31&lt;/h5&gt;
&lt;p&gt;那天晚上回去以后，牛大力想起一段更早的对话。&lt;/p&gt;
&lt;p&gt;案发前一周，Derek在会议室单独找过他。没骂人，也没拍桌子，只是用那种过分温和的语气说：“Dali，下周董事会之后，一切都会不一样。你要提前做好心理准备。”&lt;/p&gt;
&lt;p&gt;当时他以为Derek在说组织调整，或者融资节奏。现在回看，那句话像一个提前写好的判决，只是他当时听不懂。&lt;/p&gt;
&lt;p&gt;凌晨一点，凯文发消息问他要不要出来透气。&lt;/p&gt;
&lt;p&gt;他们去了凯文公寓，电视里放的是《无间道》。两个人都没怎么喝酒，只开了一罐气泡水。&lt;/p&gt;
&lt;p&gt;电影播到后半段，凯文忽然按了暂停。&lt;/p&gt;
&lt;p&gt;“你说刘建明最后是真的疯了，”他问，“还是一直清醒，只是选择活在谎言里？”&lt;/p&gt;
&lt;p&gt;牛大力盯着暂停画面里那张脸，说：“也许没有区别。”&lt;/p&gt;
&lt;p&gt;凯文笑了一下，没接话，按下播放。&lt;/p&gt;
&lt;p&gt;窗外是圣何塞凌晨的安静街区。屋里是粤语对白和空调的低噪。手机屏幕一会儿亮一会儿灭，LinkedIn推送着某某人“Thrilled to announce”升职、融资、跳槽，像一场永不落幕的线上庆典。&lt;/p&gt;
&lt;p&gt;现实里，每个人都在用不同方式崩溃。&lt;/p&gt;
&lt;p&gt;第二天早上，Kim给牛大力发来一条简短短信：&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;We are focusing on Lina as primary suspect for now.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;牛大力盯着那行字看了很久，心里却没有任何“案子快结束了”的轻松。&lt;/p&gt;
&lt;p&gt;他说不上来哪里不对。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;第五章完美的不在场&quot;&gt;第五章：「完美的不在场」&lt;/h4&gt;
&lt;h5 id=&quot;32&quot;&gt;32&lt;/h5&gt;
&lt;p&gt;第三次问询时，Detective Kim没再从“那天早上”问起。&lt;/p&gt;
&lt;p&gt;她把一份打印报告推到牛大力面前，手指压在最后一行。&lt;/p&gt;
&lt;p&gt;“法医初步意见，”她说，“死亡时间窗口：周三晚到周四晚。”&lt;/p&gt;
&lt;p&gt;牛大力看着那行字，第一反应不是震惊，是一种荒谬的错位感。周三晚到周四晚，像一个被随手写下的范围，宽得足够容纳所有人的侥幸。&lt;/p&gt;
&lt;p&gt;“你们现在更怀疑谁？”他问。&lt;/p&gt;
&lt;p&gt;Kim翻开下一页，是Derek电脑里恢复出的邮件草稿。&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Re: Product Leadership Change&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;收件人是董事会，内容暗示李娜在下次会议后会被降职。草稿最后修改时间显示周四下午。&lt;/p&gt;
&lt;p&gt;“有动机，有权限进顶层，周四晚没有可靠的不在场证明。”Kim说，“李娜目前是第一嫌疑人。”&lt;/p&gt;
&lt;p&gt;她停了一秒，又补了一句：“Andrei也没排除。楼梯间拍到一个模糊人影，穿深灰大衣，体型和他接近。”&lt;/p&gt;
&lt;p&gt;牛大力点点头，像一个配合调查的普通证人。&lt;/p&gt;
&lt;p&gt;可他心里没有“快破案了”的轻松。只有一层更薄、更冷的东西，贴在胸口。&lt;/p&gt;
&lt;h5 id=&quot;33&quot;&gt;33&lt;/h5&gt;
&lt;p&gt;晚上八点，凯文给他发消息：&lt;/p&gt;
&lt;p&gt;“家里没菜，去不去大华？”&lt;/p&gt;
&lt;p&gt;他们在Ranch 99的冷冻柜前站了快十分钟。凯文拿起一袋思念水饺，看配料表，又放回去；又拿起来，再放回去。&lt;/p&gt;
&lt;p&gt;“你知道我妈包的饺子是什么馅吗？”凯文问，“韭菜鸡蛋。她会放一点虾皮，别人家都不放。”&lt;/p&gt;
&lt;p&gt;“我妈也是韭菜鸡蛋。”牛大力说。&lt;/p&gt;
&lt;p&gt;“不一样的，”凯文笑了笑，“每家人的韭菜鸡蛋都不一样。”&lt;/p&gt;
&lt;p&gt;他盯着袋子背面的营养表，声音突然低下来。&lt;/p&gt;
&lt;p&gt;“我四年没回去了。每次打电话我妈都问，什么时候回来。我都说快了快了。快了。四年了。”&lt;/p&gt;
&lt;p&gt;说完他把那袋水饺扔进购物车，语气一秒钟切回平常。&lt;/p&gt;
&lt;p&gt;“走，看看五花肉。上次买的太瘦，烤出来像纸板。”&lt;/p&gt;
&lt;p&gt;他们推着车从冷冻区走到生鲜区，路过一排排写着“限时特价”的红牌子。牛大力忽然想起他们这些人也是这样活着：白天在圣何塞调参数、写文档、讨论product-market fit；晚上在微信里跟国内家人报平安，假装自己没有错过任何一个节日。&lt;/p&gt;
&lt;p&gt;他们同时活在两个时区里。&lt;/p&gt;
&lt;h5 id=&quot;34&quot;&gt;34&lt;/h5&gt;
&lt;p&gt;第二天中午，办公室微波炉前排着队。凯文端着餐盒，像随口聊天那样说：&lt;/p&gt;
&lt;p&gt;“Costco牛肉又涨价了，离谱。”&lt;/p&gt;
&lt;p&gt;牛大力抬头看他，愣了半秒。&lt;/p&gt;
&lt;p&gt;“你昨天是不是也说过这句？”&lt;/p&gt;
&lt;p&gt;“有吗？”凯文笑，“那说明它真的涨得很离谱。”&lt;/p&gt;
&lt;p&gt;Ravi在旁边插话：“CVE那个事你们怎么看？影响到底多大？”&lt;/p&gt;
&lt;p&gt;凯文接得很快，几乎抢在所有人前面：“对啊，我也正想问——”&lt;/p&gt;
&lt;p&gt;“昨天不是已经修完了吗？”另一个工程师把饭盒从微波炉里拿出来，“补丁昨晚就merge了。”&lt;/p&gt;
&lt;p&gt;“对，今天就正常监控了。”Ravi说。&lt;/p&gt;
&lt;p&gt;凯文停了一下，笑着耸肩：“行，那我白紧张了。”&lt;/p&gt;
&lt;p&gt;话题立刻被带去别处——有人在抱怨停车费，又有人在争论哪家拉面店的汤底最咸。牛大力也跟着笑，但那一秒短暂停顿像一粒沙，卡在他记忆里。&lt;/p&gt;
&lt;h5 id=&quot;35&quot;&gt;35&lt;/h5&gt;
&lt;p&gt;当晚七点多，凯文在Slack敲他：&lt;/p&gt;
&lt;p&gt;“新开那家拉面去不去？我今天特别想吃拉面。”&lt;/p&gt;
&lt;p&gt;“走。”&lt;/p&gt;
&lt;p&gt;店在Japantown边上，门口排了二十分钟。凯文点了最辣那档，吃到一半开始出汗，还坚持说“这家不够劲”。他们聊了半天无关紧要的东西：101哪一段永远堵，GitHub Copilot最近又改了什么交互，旧金山的房租到底是不是集体幻觉。&lt;/p&gt;
&lt;p&gt;回程路上凯文说：“你看，今天其实也没那么糟。”&lt;/p&gt;
&lt;p&gt;牛大力当时点了头。&lt;/p&gt;
&lt;p&gt;后来他在问询室里回忆“那天晚上”时，脑子里第一个跳出来的就是这碗拉面。热气、排队号码、凯文说“今天特别想吃拉面”的语气。这个“今天”太具体了，具体得像一颗钉子，把他整段记忆钉在“案发当天=周四”的木板上。&lt;/p&gt;
&lt;p&gt;可那块木板，本来就是凯文递给他的。&lt;/p&gt;
&lt;h5 id=&quot;36&quot;&gt;36&lt;/h5&gt;
&lt;p&gt;第四次问询，Kim把一叠时间线放在桌上，从左到右排开：门禁、Slack、Git、外卖单、网约车记录。&lt;/p&gt;
&lt;p&gt;“证据在收拢。”她说，“李娜这边很快会有结果。”&lt;/p&gt;
&lt;p&gt;牛大力盯着那叠纸，听见自己开口：“凯文……有问题吗？”&lt;/p&gt;
&lt;p&gt;Kim看了他一眼。“目前没有。周四晚他和你长时间同处，时间戳很干净。比很多人都干净。”&lt;/p&gt;
&lt;p&gt;她说“很干净”的时候语气很平，像在描述一份格式正确的日志。&lt;/p&gt;
&lt;p&gt;牛大力想起另一个时间段：周三晚上，CVE全员响应那会儿，凯文说去买饭，后来隔了很久才回来。那段空白他本来已经忘了，或者说，他让自己忘了。&lt;/p&gt;
&lt;p&gt;“还有别的信息吗？”Kim问。&lt;/p&gt;
&lt;p&gt;牛大力沉默了几秒，最终摇头。&lt;/p&gt;
&lt;p&gt;“没有了。”&lt;/p&gt;
&lt;p&gt;他知道自己在做什么。&lt;/p&gt;
&lt;p&gt;他也知道自己为什么这么做。&lt;/p&gt;
&lt;p&gt;有些人你认识太久，久到你宁可怀疑自己的记忆，也不愿先怀疑他。&lt;/p&gt;
&lt;p&gt;尤其当那个人是凯文。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;第六章星期三--hes-replaceable&quot;&gt;第六章：「星期三 / He’s Replaceable」&lt;/h4&gt;
&lt;h5 id=&quot;37&quot;&gt;37&lt;/h5&gt;
&lt;p&gt;牛大力是在公司会议室写第二份书面陈述时发现不对劲的。&lt;/p&gt;
&lt;p&gt;白板上还留着前一天的路线图：Q1、Q2、latency、ARR，几个词被擦得只剩一层浅灰色影子。空调吹得太冷，他把连帽衫拉链拉到喉咙，盯着电脑屏幕上那行字：&lt;/p&gt;
&lt;p&gt;“那天晚上大家都在修vLLM漏洞。”&lt;/p&gt;
&lt;p&gt;他手停在键盘上，突然想起CVE的披露时间是周三下午五点半。补丁也是周三深夜合并的。周四晚上办公室不该还有那种“production还没patch”的集体紧张。&lt;/p&gt;
&lt;p&gt;如果他的记忆里有那种紧张，那就不是周四。&lt;/p&gt;
&lt;p&gt;他盯着那行字，像盯着一条本来就在那里的裂缝，直到它一点一点张开。&lt;/p&gt;
&lt;h5 id=&quot;38&quot;&gt;38&lt;/h5&gt;
&lt;p&gt;“不可能。”他低声说了一句。&lt;/p&gt;
&lt;p&gt;但脑子已经开始自动回放。&lt;/p&gt;
&lt;p&gt;周三和周四像两段录音，被人剪开又重新拼接。Philz咖啡、深蓝连帽衫、Costco牛肉涨价、Slack里几乎一模一样的meme、晚上长时间pair programming，所有锚点都在重复。重复到最后，连“那天”这个词都变得可疑。&lt;/p&gt;
&lt;p&gt;凯文没有伪造一段记忆。&lt;/p&gt;
&lt;p&gt;凯文只是把两天做成了同一天。&lt;/p&gt;
&lt;p&gt;牛大力打开通讯录，给Ravi打过去。&lt;/p&gt;
&lt;h5 id=&quot;39&quot;&gt;39&lt;/h5&gt;
&lt;p&gt;Ravi接电话时背景音轰得像机场。&lt;/p&gt;
&lt;p&gt;“Dali？等会儿等会儿，我这把马上打完。这个赛季平衡组是疯了吗，法师伤害砍成这样——还有印度服延迟又上去了，我ping值现在一百八，你敢信？”&lt;/p&gt;
&lt;p&gt;牛大力没接他的话，直接问：“周三晚上修CVE那会儿，凯文是不是出去过？”&lt;/p&gt;
&lt;p&gt;Ravi那边先是键盘噼里啪啦，然后是半秒安静。&lt;/p&gt;
&lt;p&gt;“出去过啊，”他说，“他说去买晚饭。挺久的，差不多两小时吧。我那会儿还在找他。”&lt;/p&gt;
&lt;p&gt;“找他干嘛？”&lt;/p&gt;
&lt;p&gt;“我有个和漏洞相关的edge case想让他看，发Slack没人回，工位也没人。后来补丁都merge了我就没再找了。第二天当然不会再找，事情都过去了。”&lt;/p&gt;
&lt;p&gt;牛大力闭上眼，握着手机的手心出了一层薄汗。&lt;/p&gt;
&lt;p&gt;Ravi在电话那头继续抱怨：“你突然问这个干嘛？等等，我被秒了……我靠这游戏——”&lt;/p&gt;
&lt;p&gt;“没事。”牛大力说，“谢谢。”&lt;/p&gt;
&lt;p&gt;挂断之后，他对着黑掉的屏幕坐了很久。&lt;/p&gt;
&lt;p&gt;法医写的是周三晚到周四晚。&lt;/p&gt;
&lt;p&gt;Ravi记得凯文周三消失两小时。&lt;/p&gt;
&lt;p&gt;而他自己，一直在拿周四的拉面给周三作证。&lt;/p&gt;
&lt;h5 id=&quot;40&quot;&gt;40&lt;/h5&gt;
&lt;p&gt;牛大力把更新后的陈述发给Kim，只写了两行：&lt;/p&gt;
&lt;p&gt;“你们看错了一天。请重查周三晚上。”&lt;/p&gt;
&lt;p&gt;二十分钟后，Kim电话打来。&lt;/p&gt;
&lt;p&gt;“你现在在哪？”&lt;/p&gt;
&lt;p&gt;“公司。”&lt;/p&gt;
&lt;p&gt;“别走。我十五分钟到。”&lt;/p&gt;
&lt;p&gt;Kim到的时候没带寒暄，直接把平板转给他看。她已经让技术组回拉周三的门禁和楼内监控。&lt;/p&gt;
&lt;p&gt;19:02，凯文从工程区离开，进了楼梯间监控盲区。&lt;/p&gt;
&lt;p&gt;21:07，他从同一处楼梯口返回工位区域。&lt;/p&gt;
&lt;p&gt;“之前我们默认案发在周四，只调了周四影像。”Kim说，“你这条线把窗口打开了。”&lt;/p&gt;
&lt;p&gt;她又翻到另一页：周三晚间，顶层附近没有凯文的个人门禁记录，但Derek的卡在21:14触发过一次。&lt;/p&gt;
&lt;p&gt;Kim抬头看他。&lt;/p&gt;
&lt;p&gt;“这不是巧合了。”&lt;/p&gt;
&lt;h5 id=&quot;41&quot;&gt;41&lt;/h5&gt;
&lt;p&gt;凌晨一点，警方在凯文公寓楼下把人带走。&lt;/p&gt;
&lt;p&gt;牛大力没有去现场。他坐在自己车里，看着仪表盘上的时间从00:58跳到01:03。手机震了一下，是Kim发来的短信：&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;He is in custody.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;第二天下午，Kim让他去看一段审讯录像。&lt;/p&gt;
&lt;p&gt;画面里的凯文穿着灰色囚服，头发没梳，整个人看起来比平时瘦了一圈。他听完问题，没有立刻反驳，只是很慢地抹了一下脸。&lt;/p&gt;
&lt;p&gt;“周三你去哪里了？”Kim问。&lt;/p&gt;
&lt;p&gt;“顶楼。”凯文说。&lt;/p&gt;
&lt;p&gt;“你为什么要制造周四的不在场？”&lt;/p&gt;
&lt;p&gt;“因为你们会先查周四。”&lt;/p&gt;
&lt;p&gt;“你都做了什么？”&lt;/p&gt;
&lt;p&gt;凯文把过程说得几乎像技术复盘：&lt;/p&gt;
&lt;p&gt;复制咖啡接龙，复制午餐对话，复制Slack节奏，复制衣着；晚上主动拉牛大力pair四小时，把注意力锁死；用Derek手机伪造远程办公消息，锁会议室，调低空调；在Derek电脑里留给李娜的降职草稿，用模糊楼梯监控影子牵Andrei，用Ravi账号留一次敏感搜索，再在自己身上故意留下“看起来太明显”的几处痕迹，等警察排除。&lt;/p&gt;
&lt;p&gt;“唯一没复制成功的是CVE。”凯文说，“周四我想再把气氛点起来，大家都说昨天已经修完了。”&lt;/p&gt;
&lt;p&gt;他说这句的时候笑了一下，那种知道程序里有个bug终于被复现出来的笑。&lt;/p&gt;
&lt;h5 id=&quot;42&quot;&gt;42&lt;/h5&gt;
&lt;p&gt;“动机呢？”Kim问。&lt;/p&gt;
&lt;p&gt;凯文沉默了很久。&lt;/p&gt;
&lt;p&gt;“Derek准备在董事会把Dali推出去，”他说，“合规背锅。开掉他，再切割。签证也一起断。”&lt;/p&gt;
&lt;p&gt;“你怎么知道？”&lt;/p&gt;
&lt;p&gt;“我听见的。周二晚上，他跟法务在电话里说，‘He’s just an engineer. He’s replaceable.’”&lt;/p&gt;
&lt;p&gt;审讯室里静了几秒。&lt;/p&gt;
&lt;p&gt;凯文盯着桌面继续说：“你们都觉得这是商业决策。对你们是。对我们不是。”&lt;/p&gt;
&lt;p&gt;他抬起眼，声音第一次有了裂口。&lt;/p&gt;
&lt;p&gt;“大三那年我抑郁，差一点从楼顶跳下去。那时候每天给我送饭的人是他。三个星期。没讲大道理，也没问我怎么了，就把饭放门口。你问我为什么做这件事？”&lt;/p&gt;
&lt;p&gt;他停下来，像是在找一个最短、最不容易被误解的句子。&lt;/p&gt;
&lt;p&gt;“他救过我的命。他自己都不知道。”&lt;/p&gt;
&lt;h5 id=&quot;43&quot;&gt;43&lt;/h5&gt;
&lt;p&gt;三天后，牛大力去县看守所探视。&lt;/p&gt;
&lt;p&gt;隔着玻璃电话接通，凯文先开口：“你最近去那家新开的奶茶店了吗？就是Santa Clara那家，门口总在排队的。”&lt;/p&gt;
&lt;p&gt;“去过一次。”牛大力说，“太甜了，排队还特别久。”&lt;/p&gt;
&lt;p&gt;“可惜。”&lt;/p&gt;
&lt;p&gt;“嗯。”&lt;/p&gt;
&lt;p&gt;他们又聊了两句无关紧要的：Ranch 99最近五花肉涨价，Milpitas那家兰州拉面换了老板，Andrei果然还是每天九点零七分第一杯咖啡。&lt;/p&gt;
&lt;p&gt;谁都没有提案子。&lt;/p&gt;
&lt;p&gt;谁都知道案子就在两人中间，像玻璃里那条看不见的接缝。&lt;/p&gt;
&lt;p&gt;最后凯文说：“对不起。”&lt;/p&gt;
&lt;p&gt;牛大力点了点头，没有说“没关系”。&lt;/p&gt;
&lt;p&gt;电话挂断，玻璃里只剩下他自己的脸。&lt;/p&gt;
&lt;h5 id=&quot;44&quot;&gt;44&lt;/h5&gt;
&lt;p&gt;那天傍晚，他回到mala.ai停车场，坐进车里。&lt;/p&gt;
&lt;p&gt;101还是堵在老地方，Philz还是同一个味道，Slack照样有人在频道里发“quick sync?”，世界继续以一种稳定且冷漠的速度向前滚。&lt;/p&gt;
&lt;p&gt;他把车点着火，又熄火，再点一次。&lt;/p&gt;
&lt;p&gt;很多事情没有变。&lt;/p&gt;
&lt;p&gt;但有一件事终于变得非常清楚：&lt;/p&gt;
&lt;p&gt;今天不是昨天。&lt;/p&gt;
&lt;p&gt;周三不是周四。&lt;/p&gt;
&lt;p&gt;人也不是模块。&lt;/p&gt;</content:encoded><category>Fiction</category></item><item><title>Bitcoin Reached 100k Today</title><link>https://xingliu.me/2024/12/04/Bitcoin-reached-100k/</link><guid isPermaLink="true">https://xingliu.me/2024/12/04/Bitcoin-reached-100k/</guid><description>Bitcoin reached $100k, and why that felt good for reasons other than the gains.</description><pubDate>Wed, 04 Dec 2024 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Bitcoin finally reached $100k today (20241204). I am feeling very excited right now, not because of the unrealized gain on my account, but because the reality is going in the direction I believed it would.&lt;/p&gt;
&lt;p&gt;Between 2020 and 2021, I started to realize that Bitcoin and crypto as a whole had passed the turning point that determines its survival, as the consensus reached a certain magnitude that would prevent its demise. Starting from then, I began to DCA into Bitcoin and a few other cryptos. The amount of money is not that impressive and won’t change my life, but serves as an anchor into this topic.&lt;/p&gt;
&lt;p&gt;I (along with other degens) went through the harsh year of 2022, and finally today we reached the artificial milestone: $100k. This is just the start, yet still many people consider Bitcoin a scam. I am more excited to see how the price increase changes people’s views towards Bitcoin.&lt;/p&gt;
&lt;p&gt;At some point, maybe Bitcoin will become another tool that the rich use to exploit the poor, but I’m happy to take the early ride in Bitcoin’s history.&lt;/p&gt;</content:encoded><category>Crypto</category></item><item><title>My book list of 2021</title><link>https://xingliu.me/2022/01/03/book-list-of-2021/</link><guid isPermaLink="true">https://xingliu.me/2022/01/03/book-list-of-2021/</guid><description>Eight books from 2021, from The Baron in the Trees to The Millionaire Next Door.</description><pubDate>Mon, 03 Jan 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2021 passed like fly, let’s see which book I read in 2021:
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-baron-in-the-trees-by-italo-calvino&quot;&gt;“The Baron in the Trees” by Italo Calvino&lt;/h2&gt;
&lt;p&gt;He is complete only after living on the trees.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;zen-and-the-art-of-motorcycle-maintenance-by-robert-m-pirsig&quot;&gt;“Zen and the Art of Motorcycle Maintenance” by Robert M. Pirsig&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;rich-dad-poor-dad-by-robert-kiyosaki&quot;&gt;“Rich Dad Poor Dad” by Robert Kiyosaki&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;born-a-crime-by-trevor-noah&quot;&gt;“Born a Crime” by Trevor Noah&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-martian-chronicles-by-ray-bradbury&quot;&gt;“The Martian Chronicles” by Ray Bradbury&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-book-of-sand-by-jorge-luis-borges&quot;&gt;“The Book of Sand” by Jorge Luis Borges&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-legend-of-the-condor-heroes-by-jin-yong&quot;&gt;“The Legend of the Condor Heroes” by Jin Yong&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-millionaire-next-door-by-thomas-j-stanley&quot;&gt;“The Millionaire Next Door” by Thomas J. Stanley&lt;/h2&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;</content:encoded><category>Books &amp; reading notes</category></item><item><title>DDIA Chapter 1: Reliable, Scalable, and Maintainable Applications</title><link>https://xingliu.me/2021/12/06/Designing-Data-Intensive-Application-Chapter1/</link><guid isPermaLink="true">https://xingliu.me/2021/12/06/Designing-Data-Intensive-Application-Chapter1/</guid><description>Reading notes on chapter 1 of Designing Data-Intensive Applications: reliability, scalability and maintainability.</description><pubDate>Mon, 06 Dec 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Many applications are data-intensive instead of compute-intensive, for example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Store data so that they, or another application, can find it again later (&lt;em&gt;database&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Remember the result of an expensive operation, to speed up reads (&lt;em&gt;caches&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Allow users to search data or filter in carious ways (&lt;em&gt;search indexes&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Send a message to another process, to be handled asynchronously (&lt;em&gt;stream processing&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Periodically crunch a large amount of data (&lt;em&gt;batch processing&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When building an application, we need to figure out which tools and which approaches are the most appropriate for the task at hand.&lt;/p&gt;
&lt;h2 id=&quot;thinking-about-data-systems&quot;&gt;Thinking About Data Systems&lt;/h2&gt;
&lt;p&gt;Many new tools for data storage and processing emerged recently, they are optimized for a variety different use cases, and they no
longer neatly fit into traditional categories. For example, &lt;em&gt;Redis&lt;/em&gt; are datastores that are also used as message queues, &lt;em&gt;Kafka&lt;/em&gt;
are message queues with database-like durability guarantees.&lt;/p&gt;
&lt;p&gt;We will focus on 3 concerns that are important in most software systems:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reliability&lt;/strong&gt;: The system should continue to work &lt;em&gt;correctly&lt;/em&gt; (performing the correct function at the desired level of performance)
even in the face of &lt;em&gt;adversity&lt;/em&gt; (hardware or software faults, and even human error).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: As the system &lt;em&gt;grows&lt;/em&gt; (in data volume, traffic volume, or complexity), there should be reasonable ways of dealing with
that growth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;: Over time, many different people will work on the system (engineering and operations, both maintaining current
behavior and adapting the system to new use cases), and they should all be able to work on it &lt;em&gt;productively&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reliability&quot;&gt;Reliability&lt;/h2&gt;
&lt;p&gt;Reliability means “continuing to work correctly, even when things go wrong”.&lt;/p&gt;
&lt;p&gt;The things that can go wrong are called &lt;em&gt;faults&lt;/em&gt;, and systems that anticipate faults and can cope with them are called &lt;em&gt;fault-tolerant&lt;/em&gt; or
&lt;em&gt;resilient&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Note that a fault is different than a failure. It is impossible to reduce the probability of a fault to zero; therefore it is usually best to
design fault-tolerance mechanisms that prevent faults from causing failures.&lt;/p&gt;</content:encoded><category>Books &amp; reading notes</category></item><item><title>I Changed Job</title><link>https://xingliu.me/2021/09/07/i-changed-my-job/</link><guid isPermaLink="true">https://xingliu.me/2021/09/07/i-changed-my-job/</guid><description>Leaving Yahoo for Google in 2021, and how the job search went: offers, rejections and withdrawals at six companies.</description><pubDate>Tue, 07 Sep 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just a quick update. This week will be my last week at Yahoo. Starting from next week I’ll be working at Google.&lt;/p&gt;
&lt;p&gt;The reason I decided to switch the job is I heard Apollo will acquire Verizon Media, and since Apollo is a private equity company. I don’t think Yahoo will thrive as a tech company.&lt;/p&gt;
&lt;p&gt;I interviewed with 6 companies: Google (Offer), Robinhood (Offer), LinkedIn (Rejection), Amazon (Rejection), Facebook (Withdraw Onsite), TikTok (Withdraw Onsite).&lt;/p&gt;
&lt;p&gt;It was tough to choose between Google and Robinhood. I finally accepted Google’s offer based on many reasons. Looking forward to the new journey.&lt;/p&gt;</content:encoded><category>Life &amp; work</category></item><item><title>A newbie guide of how to buy crypto with lower fees</title><link>https://xingliu.me/2021/02/18/how-to-buy-crypto-with-lower-fees/</link><guid isPermaLink="true">https://xingliu.me/2021/02/18/how-to-buy-crypto-with-lower-fees/</guid><description>How fees on Coinbase, Coinbase Pro and Binance.US eat into a trade, and a cheaper way to buy.</description><pubDate>Thu, 18 Feb 2021 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there, Bitcoin hits 56k today and I’m here to introduce a way to buy Bitcoin or other major cryptos with relatively lower fees. I am just a newbie as well, you are welcome to tell me an even better approach to reduce the annoying fees.&lt;/p&gt;
&lt;p&gt;I wanna mention that I do not recommend use Robinhood to trade crypto because you won’t even get a wallet for the crypto you own.&lt;/p&gt;
&lt;p&gt;Years ago, I used &lt;a href=&quot;https://www.coinbase.com/&quot;&gt;Coinbase&lt;/a&gt; to buy Bitcoin, apparently, it’s the most convenient app for most people to buy crypto. But they also charge minimum of 1.49% fees for any buy/sell transactions, if your transaction amount is lower than $200, the expense ratio is even higher.&lt;/p&gt;
&lt;p&gt;Easily we can switch to &lt;a href=&quot;https://pro.coinbase.com/&quot;&gt;Coinbase Pro&lt;/a&gt; which only charge you 0.50% if you are a new user. But 0.50% still sounds high, especially when most brokers charge 0 commission fees nowadays.&lt;/p&gt;
&lt;p&gt;Then we found an awesome crypto exchange: &lt;a href=&quot;https://www.binance.us/en/home&quot;&gt;Binance.US&lt;/a&gt;, they only charge you 0.10% fees for transactions as a new user, and if you buy a little amount of BNB (a crypto that was created by Binance) and pay you fees by BNB, you will get 0.75% discount which leads to equivalent 0.075% fees for transactions.&lt;/p&gt;
&lt;p&gt;Let’s do quick math to see how transaction fees can eat your profits: you deposit 10k to buy Bitcoin, and assume you sold it when the price of Bitcoin up 50%! Without any fees, here is how many profits you can keep at different exchange (round to the nearest integer):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th scope=&quot;col&quot;&gt;Exchange&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Transaction fees&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Original Funds&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Original value in Bitcoin&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Final value in Bitcoin&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Final funds&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Profits&lt;/th&gt;
&lt;th style=&quot;text-align:center&quot; scope=&quot;col&quot;&gt;Percentages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Benchmark&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;0&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$10,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$10,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$15,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$15,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$5,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coinbase&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;1.49%&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$10,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$9,851&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,777&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,557&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$4,557&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;91%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coinbase Pro&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;0.5%&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$10,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$9,950&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,925&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,850&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$4,850&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;97%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binance.US&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;0.075%&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$10,000&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$9,993&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,990&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$14,980&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;$4,980&lt;/td&gt;
&lt;td style=&quot;text-align:center&quot;&gt;99.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;br&gt;Lower transaction fees can protect most your profits for even 1 transaction, if you seriously want to invest or trade crypto, I strongly recommend minimizing the transaction fee. But there is a problem about Binance.US: a new user can hardly deposit USD into the account. Here are the steps you can follow to bypass as much fees as possible:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.coinbase.com/join/liu_p8&quot; rel=&quot;sponsored&quot;&gt;Create a Coinbase/Coinbase Pro account&lt;/a&gt;, link you bank account and deposit USD.&lt;/li&gt;
&lt;li&gt;Buy USDC (USD Coin) with USD with 0 fee, 1 USDC almost always worth 1 USD.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://accounts.binance.us/en/register?ref=53283116&quot; rel=&quot;sponsored&quot;&gt;Create a Binance.US account&lt;/a&gt;, go to &lt;em&gt;Wallet&lt;/em&gt; -&amp;gt; &lt;em&gt;Deposit&lt;/em&gt;, find and copy your USDC wallet address.&lt;/li&gt;
&lt;li&gt;Go back to Coinbase, go to &lt;em&gt;Send/Receive&lt;/em&gt;, paste your USDC wallet address from Binance.US and send all your USDC, &lt;strong&gt;it will cost you few USDC as network fee&lt;/strong&gt;, this fee is paid to Ethereum (underlying infrastructure of USDC) and is irrelevant with how much USDC you sent, so you should send all your USDC at once.&lt;/li&gt;
&lt;li&gt;Once you received USDC in your Binance.US account, convert USDC to BUSD (Binance USD) with 0 fee, 1 USDC almost always worth 1 BUSD.&lt;/li&gt;
&lt;li&gt;Buy few BNB with BUSD as your transaction fees.&lt;/li&gt;
&lt;li&gt;Buy crypto you want with BUSD and enjoy the 0.075% transaction fees from now.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So this is the optimal path to reduce the transaction fees I found so far, hope this will help anyone who’s new to investing crypto!&lt;/p&gt;</content:encoded><category>Crypto</category></item><item><title>My book list of 2020</title><link>https://xingliu.me/2020/12/31/book-film-list-of-2020/</link><guid isPermaLink="true">https://xingliu.me/2020/12/31/book-film-list-of-2020/</guid><description>Eleven books from 2020, from Le Petit Prince to Born a Crime, most with a one-line verdict.</description><pubDate>Thu, 31 Dec 2020 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2020 is surely a unique year, I went through ups and downs, like everyone else. One gem I received is I developed the habit of reading every day, it was tough at first, gradually I started to enjoy it. I’d like to share my favorite books I read in 2020:
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;le-petit-prince-by-antoine-de-saint-exupéry&quot;&gt;“Le Petit Prince” by Antoine de Saint-Exupéry&lt;/h2&gt;
&lt;p&gt;It’s a mirror, everyone see his/her own present reflection from the story, that’s why I don’t regret that I didn’t read it when I was younger.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;sternstunden-der-menschheitvierzehn-historische-miniaturen-by-stefan-zweig&quot;&gt;“Sternstunden der Menschheit：Vierzehn historische Miniaturen” by Stefan Zweig&lt;/h2&gt;
&lt;p&gt;Fate always changes inadvertently.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-case-of-the-speluncean-explorers-by-lon-l-fuller&quot;&gt;“The Case of the Speluncean Explorers” by Lon L. Fuller&lt;/h2&gt;
&lt;p&gt;Law is like a giant classifier, and people built it without code.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;why-we-buy-the-science-of-shopping-by-paco-underhill&quot;&gt;“Why We Buy: The Science of Shopping” by Paco Underhill&lt;/h2&gt;
&lt;p&gt;We make money from other people’s shopping, then we go shopping and spend the money. So we’d better know something about the science of shopping.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;atomic-habits-by-james-clear&quot;&gt;“Atomic Habits” by James Clear&lt;/h2&gt;
&lt;p&gt;I guess it works, now I can read everyday.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;principles-of-economics-by-n-gregory-mankiw&quot;&gt;“Principles of Economics” by N. Gregory Mankiw&lt;/h2&gt;
&lt;p&gt;Finally cleared that reading debt, I prefer the microeconomics part.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-moon-and-sixpence-by-william-somerset-maugham&quot;&gt;“The Moon and Sixpence” by William Somerset Maugham&lt;/h2&gt;
&lt;p&gt;He fulfilled his dream, but he is a selfish man.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;no-longer-human-by-osamu-dazai&quot;&gt;“No Longer Human” by Osamu Dazai&lt;/h2&gt;
&lt;p&gt;The coward is afraid of happiness, and he gets hurt when he touches cotton.
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;clean-code-by-robert-cecil-martin&quot;&gt;“Clean Code” by Robert Cecil Martin&lt;/h2&gt;
&lt;p&gt;(ongoing)
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;the-baron-in-the-trees-by-italo-calvino&quot;&gt;“The Baron in the Trees” by Italo Calvino&lt;/h2&gt;
&lt;p&gt;(ongoing)
&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2 id=&quot;born-a-crime-by-trevor-noah&quot;&gt;“Born a Crime” by Trevor Noah&lt;/h2&gt;
&lt;p&gt;(ongoing)&lt;/p&gt;</content:encoded><category>Books &amp; reading notes</category></item><item><title>Welcome to Jekyll!</title><link>https://xingliu.me/2020/12/26/hello-world/</link><guid isPermaLink="true">https://xingliu.me/2020/12/26/hello-world/</guid><description>The first post on this blog: the Jekyll template’s sample, with highlighted code in seven languages.</description><pubDate>Sat, 26 Dec 2020 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Hello world&lt;/strong&gt;, this is my first Jekyll blog post template.&lt;/p&gt;
&lt;p&gt;I hope you like it!&lt;/p&gt;
&lt;h2 id=&quot;highlighter&quot;&gt;Highlighter&lt;/h2&gt;
&lt;h3 id=&quot;ruby&quot;&gt;Ruby&lt;/h3&gt;
&lt;div class=&quot;language-ruby highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token method-definition&quot;&gt;&lt;span class=&quot;token function&quot;&gt;show&lt;/span&gt;&lt;/span&gt;
  puts &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Outputting a very lo-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-ong lo-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-ong line&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token variable&quot;&gt;@widget&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Widget&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token symbol&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  respond_to &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;format&lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt;
    format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;html &lt;span class=&quot;token comment&quot;&gt;# show.html.erb&lt;/span&gt;
    format&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;json &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; render json&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;@widget&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;php&quot;&gt;Php&lt;/h3&gt;
&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token php language-php&quot;&gt;&lt;span class=&quot;token delimiter important&quot;&gt;&amp;lt;?php&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string double-quoted-string&quot;&gt;&quot;Hello &lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$world&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token delimiter important&quot;&gt;?&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;java&quot;&gt;Java&lt;/h3&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; java &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;html&quot;&gt;HTML&lt;/h3&gt;
&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Title!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;p&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;foo&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;Hello, World!&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;p&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/javascript&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token script&quot;&gt;&lt;span class=&quot;token language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;style&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;text/css&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token style&quot;&gt;&lt;span class=&quot;token language-css&quot;&gt;&lt;span class=&quot;token selector&quot;&gt;&lt;span class=&quot;token id&quot;&gt;#foo&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; bold&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;style&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;console&quot;&gt;Console&lt;/h3&gt;
&lt;div class=&quot;language-console highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token shell-symbol important&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token bash language-bash&quot;&gt;prints &lt;span class=&quot;token string&quot;&gt;&quot;hello, world&quot;&lt;/span&gt; to the &lt;span class=&quot;token function&quot;&gt;screen&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token info punctuation&quot;&gt;&lt;span class=&quot;token path&quot;&gt;~&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token shell-symbol important&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token bash language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; Hello, World&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token output&quot;&gt;Hello, World

&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token shell-symbol important&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token bash language-bash&quot;&gt;don&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token output&quot;&gt;&apos;t run this
&lt;/span&gt;&lt;span class=&quot;token command&quot;&gt;&lt;span class=&quot;token info punctuation&quot;&gt;&lt;span class=&quot;token path&quot;&gt;~&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token shell-symbol important&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;token bash language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-rf&lt;/span&gt; --no-preserve-root /&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;css&quot;&gt;Css&lt;/h3&gt;
&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token selector&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;token unit&quot;&gt;pt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token hexcode color&quot;&gt;#fff&lt;/span&gt; &lt;span class=&quot;token url&quot;&gt;&lt;span class=&quot;token function&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;temp.png&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt; top left no-repeat&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;yaml&quot;&gt;Yaml&lt;/h3&gt;
&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Mark McGwire
&lt;span class=&quot;token key atrule&quot;&gt;two&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Sammy Sosa
&lt;span class=&quot;token key atrule&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ken Griffey
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>Meta</category></item></channel></rss>