惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
GbyAI
GbyAI
M
MIT News - Artificial intelligence
美团技术团队
罗磊的独立博客
雷峰网
雷峰网
量子位
博客园 - 【当耐特】
Last Week in AI
Last Week in AI
D
Docker
小众软件
小众软件
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
T
Tailwind CSS Blog
WordPress大学
WordPress大学
V
V2EX
博客园_首页
腾讯CDC
The Cloudflare Blog
A
About on SuperTechFans
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Benson's blog

Enjoy life Internship AI on academic research How AI Will Change the Mobile Ecosystem Look ahead Goodbye 2025 Hacker News to Kindle Another project How to imporve english Introduction of Fraud detection PopTranslate Last day in netease Better idea between Copilot-typed and CLI-typed assistant Gemini-cli LLM Post-Training experience Papers I readed recently about LLM application Difference between LLMs and traditional computer technology GRPO Weekly-#26 AI Application Weekly-#25 AI infra and application Weekly-#24 First week as LLM inference engineer Weekly-#23 seeking job Weekly-#22 2025 New Year AutoSwitch Translate Goodbye 2024 Weekly-#20 Breaking of glass Cross Entropy Loss of Triton Weekly-#18 Cross Entropy Loss of Triton Weekly-#17 Triton Puzzles Weekly-#16 AutoBuilder
duckdb 看懂的第一个PR
Benson · 2023-10-22 · via Benson's blog

背景

duckdb 是关注到的第一个我自己平常能用到,也不是那么(四声)庞大的开源项目,刚好最近想尝试新的技术,所以就深入了解了一下。

duckdb对我的用法,就是能以本地文件为数据源,用sql语言进行查询、分析数据;平常类似的需求我都用python来解决,但远没有sql来的高效,所以duckdb还是很好地提升了我的工作效率。

第一次看duckdb issue 的时候就看到了这个,比较简单的一个bug,有人最小化复现了这个问题,就是使用 map 时,where 的限制条件无法对 map 字段生效,比如:

class="highlight">

1
2
3
4
5
6
7
8
9
10
11
12
13
create table data as from (
  values
  ([1], [3]),
  ([2], [9]),
  ([3], [15]),
  ([4], [21]),
) as t(l, r);

-- this works
select l[1], r[1], map(l, r) from data;

-- map output ignores where filter.
select l[1], r[1], map(l, r) from data where r[1] != 15;

Output:

class="highlight">

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌───────┬───────┬───────────────────────┐
│ l[1]  │ r[1]  │       map(l, r)       │
│ int32 │ int32 │ map(integer, integer) │
├───────┼───────┼───────────────────────┤
│     1 │     3 │ {1=3}                 │
│     2 │     9 │ {2=9}                 │
│     3 │    15 │ {3=15}                │
│     4 │    21 │ {4=21}                │
└───────┴───────┴───────────────────────┘


┌───────┬───────┬───────────────────────┐
│ l[1]  │ r[1]  │       map(l, r)       │
│ int32 │ int32 │ map(integer, integer) │
├───────┼───────┼───────────────────────┤
│     1 │     3 │ {1=3}                 │
│     2 │     9 │ {2=9}                 │
│     4 │    21 │ {3=15}                │
└───────┴───────┴───────────────────────┘

当时我只是挑了几个好上手 & 有趣的issue,就放下这事儿了,打算一周后有时间了再来看看怎么修复,但一周后再来看的时候,这个issue已经被人修复了,过来然开源社区的活跃度还是太强了。

想解决其他的issue,但看了半天都没有头绪。。。。于是就想看看当时这个map的issue是怎么解决的,看了半天也还是看不懂,就花了大概两个周末的时间研究了一下(一共可能花了1天),截止现在,终于看懂了核心内容。

历程

中间主要在 debug,想看看每个变量内具体的内容是什么,帮助理解代码,然后也就知道bug在哪儿,自然就知道怎么修复了。

duckdb 比较好的点是,没有依赖什么外部模块,花了点时间修了一个环境问题,我一次性就编译成功了。

进入主目录之后,执行 make debug 进行编译,./build/debug/duckdb 就是新编译好的文件,执行这个文件就进入了新编译的 duckdb中。

代码里可以用 printf 打印想要的debug日志,debug过程还比较顺利,能把 debug 信息打印出来,我就有信心能看懂这个代码了。

debug过程中,主要是在找哪个变量里存储的是核心的数据,过程中主要很多变量不知道要怎么打印,代码自定义了很多基础的类,需要翻代码,特别是 Vector 变量,还是个指针

Vector:自定义的向量类型,可以通过 *(vector.GetData() + i)打印第 i 个元素的值;通过 vector.GetType().ToString().c_str() 打印type

Vector 还指定了不同的数据类型,我暂时还不知道要怎么按照特定类型打印,默认是 unsigned int8 类型,指针每次 +1 只移动 8 个字节。

先说结论,其实核心就是最后的四行代码

class="highlight">

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (key_vector.GetVectorType() == VectorType::CONSTANT_VECTOR) {
    // 省略
    map_key_vector.Reference(expanded_const);
    value_vector.Flatten(count);
    map_value_vector.Reference(ListVector::GetEntry(value_vector));
} else if (value_vector.GetVectorType() == VectorType::CONSTANT_VECTOR) {
    // 省略
    map_value_vector.Reference(expanded_const);
    key_vector.Flatten(count);
    map_key_vector.Reference(ListVector::GetEntry(key_vector));
} else {
    // 核心变更
    key_vector.Flatten(count); // 对 key_vector 根据filter信息进行截断
    value_vector.Flatten(count); // 对 key_vector 根据filter信息进行截断
    map_value_vector.Reference(ListVector::GetEntry(value_vector)); // 把中间结果 value_vector 复制给最终结果 map_value_vector
    map_key_vector.Reference(ListVector::GetEntry(key_vector)); // 把中间结果 key_vector 复制给最终结果 map_key_vector
}

第一次接触类似项目的人(两周前的我),很难看懂这四行代码对应的含义,我也是花了很久的时间定位到这里的。

结论

第一次完整看懂了一个 cpp 项目的PR,了解了完整的流程,比如 编译、debug、测试。

但除了核心数据,大部分的代码工作量都在补全其他类型的变量,这些需要对项目非常熟悉,才能补充的比较完整,需要对项目非常熟悉才行。

Trending Tags