MoreRSS

site iconqtmuniao | 青藤木鸟修改

一名专注大规模数据系统的程序员,喜欢读书、写作、分享、羽毛球和摄影。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

qtmuniao | 青藤木鸟的 RSS 预览

从“丰巢”快递柜看 Jemalloc 的内存管理

2024-10-27 22:32:37

引子

在某些工作负载中,随着时间的推移,内存的使用会逐渐增长,直到 OOM。后面发现是内存碎片问题,而将系统默认的内存分配器(glibc malloc)换成 jemalloc ,能有效控制内存的增长上界。

为了解其背后原理,便找来 jemalloc 最初的论文:A Scalable Concurrent malloc(3) Implementation for FreeBSD 来一探究竟。当然,相比 2006 年论文发表时,当前的 jemalloc 可能已经发生了很大改变,因此本文只对当时论文内容负责。更多 jemalloc 机制,大家可以去其 github 仓库查看文档和源码。

背景

在探讨论文的主要思路之前,我们先简单回顾下内存分配器(memory allocator)的作用边界。简言之:

  1. 对下,向操作系统申请大块内存(使用 sbrkmmap 等系统调用)
  2. 对上,处理应用层的各种尺寸的内存申请请求(malloc(size)),并在应用层“表示”不用(free)后进行释放

往小了说,分配器的功能非常简单:分配释放(malloc 和 free)。想象中,实现也应该很简单,只需利用一个表来记录所有已使用内存和未分配内存( a bit of bookkeeping),然后:

  1. malloc 请求来了,先去空闲表中找,不够的话就问操作系统要
  2. free 请求来了,还回空闲表中,如果空的多了,就还给操作系统

Snowflake:云原生数仓的开创者

2024-08-25 14:41:07

Snowflake 由甲骨文的两位员工在 2012 年出来创办,一开始就瞄准云原生数仓,因此架构设计(在当时看来)非常“激进”。超前的视野带来超额的回报,Snowflake 在 2020 年正式上市,市值一度高达 700 亿美金,创造了史上规模最大的软件 IPO 记录。

本文我们综合两篇论文:The Snowflake Elastic Data WarehouseBuilding An Elastic Query Engine on Disaggregated Storage 来大致聊聊其架构设计。

本文来自我的专栏《系统日知录》,如果你觉得文章还不错,欢迎订阅支持我。

这篇文章我早就想写了,但上次在看论文时卡住了——论文信息太多,地毯式的阅读,很快就淹没在细节中,当时也只看了三分之二,就搁置了。上周(20240707)在文章 Spark:如何在云上做缩容时提到了存算分离的 snowflake ,有读者要求写下,于是便重新捡起来。

相比上次 push 的方式,本次采用 pull 的方式:即不是被动的读论文,而是先思考,如果让我设计这么一个云原生数仓,我要怎么设计,会有哪些问题等等。带着这些问题,我再去从论文中找答案,发现效率一下高了很多,也便让这篇文章没有再次难产。

人生是旷野 —— 罗素《幸福之路》

2024-07-28 08:30:37

缘于某个播客提了一嘴,便找来书在通勤时听了。这版是傅雷翻在 1939 年译的版本,有一股淡淡的老式白话风。小书不长,几天便听完。我喜欢在走路的时候听东西,所听入耳、所观入眼,哲人的凝言练语、街头的风物百态,总能在心里发生奇妙的化学反应,偶在三伏天都一激灵。

最近心绪颇为起伏,在上下班踱步听这本书时,数次给我宽慰平和,书中指出的快乐和不快乐之因,都命中了我的某些缺点和特点,因此听完觉得还是要写点东西。

罗素《幸福之路》

人类从狩猎时代进入农耕时代后,虽获得了生活的相对安稳,却也失掉了向外的探索和冒险。到工业时代,城市化加剧,进一步脱离了自然的“蓝领白领”亦是如此。只有少数的企业家才仍然保持着丛林式的生活方式。

选择安稳意味着有大量的“烦闷”(Boredom)需要排遣。但多数人过度的将注意力集中在自己的身上,比如畏罪狂(纠结于行为不符合少时的成见或社会的规训)、自溺狂(过度期待外界称许的虚荣)、自大狂(过度的权力欲望),则使得这种烦闷愈加在幻想中野蛮式的生长,直至占满人们的内心。

使用 ray.data 进行大规模数据处理(二):全局视角

2024-07-07 21:03:33

ray.data 是基于 ray core 的一层封装。依赖 ray.data,用户用简单的代码,就可以实现数据大规模的异构处理(主要指同时使用 CPU 和 GPU)。一句话总结:很简单好用,同时也有很多坑。
上一篇中,我们从用户接口出发,浅浅地梳理了一下 ray.data 的主要接口。本篇,我们从宏观的角度,大概串一下 ray.data 的基本原理。之后,我们再用几篇,结合代码细节和使用经验,探讨下比较重要的几块内容:执行调度、数据格式和避坑指南。
本文来自我的专栏《系统日知录》,如果你觉得文章还不错,欢迎订阅支持我。

概述

从高层来理解,ray.data 的一次数据处理任务大致可以分成前后相继的三阶段:

  1. 数据加载:将数据从系统外部读到 ray 的 Object Store 中 (如 read_parquet)
  2. 数据变换:利用各种算子在 Object Store 中对数据进行变换(如 map/filter/repartition)
  3. 数据写回:将 Object Store 中的数据写回外部存储(如 write_parquet)

有趣的线性代数(一):矩阵乘法

2024-06-29 21:23:11

由于对各种矩阵运算物理意义的理解总是跟不上,因此尽管多年多次尝试入门机器学习,却总是被拒之门外。偶然间同事推荐了 MIT 那门经典的线性代数公开课,听了几节,煞是过瘾,之前紧闭的大门竟有打开一丝的感觉。

因此,本系列会在每篇文章分享一些课程中有意思的点。为了避免晦涩,每章会尽可能去上下文、保持简短,请放心食用。也因此,本系列会牺牲一些精确性,且并无体系化,仅仅旨在唤起你一丢丢兴趣。注:例子都由 KimiChat 生成。

Infra 面试之数据结构五:顺序组装

2024-05-05 10:49:31

这是我在很早之前遇到的一个题,很有意思,所以到现在仍然记得。题意借用了 TCP 的上下文,要求实现 TCP 中一个“顺序组装”的关键逻辑:

  1. 对于 TCP 层来说,IP 层的 packet 是乱序的收到。
  2. 对于应用层来说,TCP 层交付的是顺序的数据。

这个题有意思的点在于,借用了 TCP 的上下文之后,就可以先和候选人讨论一些 TCP 的基础知识,然后话锋一转,引出这道题。这样既可以考察一些基础知识,也可以考察工程代码能力。

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Packet {
size_t offset;
size_t length;
uint8_t *data;
};

// 实现一个“顺序交付”语义
class TCP {
// 应用层调用:按顺序读取不超过 count 的字节数到 buf 中,并返回实际读到的字节数
size_t read(void *buf, size_t count);
// TCP 层回调:得到一些随机顺序的 IP 层封包
void receive(Packet* p);
// TCP 层回调:数据发完,连接关闭
void finish();
};