Archive
文件页:dirty、write、stale TLB 等等
本文主要介绍脏页在内存回收、读写操作并发这些内存活动中,是如何保证一致性的。尤其是是回收过程,对于有页表映射的文件页面,涉及到刷 tlb 相关的,这些地方尤为谨慎。
对于具有写权限、被修改为脏页(Dirty)、且需要写回磁盘的共享文件映射页面(MAP_SHARED + PROT_WRITE),结合内核源码(vmscan.c 和 rmap.c),整个回收与写回生命周期以及在各时间节点通过 stale TLB 访问 的行为分析如下:
回收过程
一般情况下,是不会回收脏页的,尤其是对于普通文件页。而那些后备是 zram 的匿名脏页,回收的概率倒是比较大。他们在处理上基本相似。
我们这里列举最坏的情况下,比如 kswapd 即回收文件脏页,也回收匿名脏页。
[用户态修改页面] -> PTE 变 Dirty, CPU 缓存 Writable TLB
│
▼
[回收开始: shrink_folio_list()]
│
▼
[1. try_to_unmap()] ──────► 清除 PTE (PTE 变无效),但延迟刷新 TLB (未发 IPI)... 页表共享:一种动态内存扩缩设计
背景
PolarDB:PolarDB数据库共享内存三种形式 & 内存扩缩
当前数据库有三种共享内存形式,是同时存在的:
- mmap方式申请的anonymous shared memory;地址通过fork传递;
- sysv方式申请的buffer pool;这部分分为两个功能,一个叫做persisted buffer pool,这部分是为了我们能在异常重启后继续使用内存,地址通过fork传递;一个叫做dsga,就是我们的共享内存的扩缩,地址通过attach detach内存段实现地址共享(维护了一个1TB的虚拟内存地址,通过fork传递);
- 并行查询的动态共享内存,根据参数可以使用mmap/sysv/posix三种方式,地址通过attach detach内存段实现地址共享。每个进程有自己的内存段地址;
站在OS的角度,这里有两类shared memory需要使用页表共享。
在线扩缩共享内存:
现有的扩缩方式,需要在父进程调整后,attach和detach子进程,在子进程数量大的时候这种通信开销较大。如果使用页表共享,仅仅需要父进程调用madvise(MADV_DONTNEED)即可。如此即可将使用的内存释放出来。扩缩的需求是能够对最小到2M粒度的内存(边界都是2M对齐)进行madvise(MADV_DONTNEED)操作。
了解FlashAttention-1、2、3、4
已有的几种大模型上下文支持情况:
厂商 | 代表模型系列 | 官方标称上下文长度 | 换算成中文 | 核心标签 / 特点 |
Gemini 1.5 Pro / 3 Pro Gemini 1.5 Flash / 3.5 Flash | 2M ~ 10M (200万~1000万 Token) | 150万 ~ 750万字 | 长上下文绝对王者 可吞下一整年聊天记录、数十小时音频或长视频 | |
Anthropic | Claude 4.6 / 5 系列 (包括 Sonnet / Opus) | 1M (API 阶段) (常用 200k 基础窗口) | 约 70万 ~ 80万字 | ... |