[Lab] CMU 15-445/645 : Project#0 - C++ Primer
[Lab] CMU 15-445/645 : Project#0 - C++ Primer
背景
- 这两年工作内容主要是数据库中间件开发,半路出家,缺少数据库内核的领域知识。仅靠使用经验很难再有提升了,计划从基础开始系统补充数据库领域知识。第一个目标是做完 CMU 15-445/645 的 lab,宁可慢慢做,但是保证一定独立完成。
- fall2024 project列表
- 第一个project是主要是熟悉c++开发,把开发环境准备好
环境准备
bustub 需要在ubuntu环境编译运行,我手上有个centos的服务器,因此准备采用ubuntu的docker,把常用依赖打成镜像,挂载一个本地目录。代码开发在centos,编译、运行、Debug在docker环境。过程熟悉一下相关工具和c++语法。
Docker 常用命令
命令 | 说明 |
---|---|
docker run -t -i ubuntu:latest /bin/bash | 运行镜像 |
docker ps | 查看运行的容器 |
docker ps -a | 查看所有容器,包括停止的 |
docker commit bbe7f183f00b bustub-sys | 将container_id对应的容器的当前环境打一个镜像 |
docker images | 查看本地可用的镜像 |
docker run -v path/cmu15445:/work -it bustub-sys /bin/bash | -v挂载本地目录到容器内的指定目录 |
docker start 5aafed5504f9 | 启动container_id对应容器 |
docker exec -it 5aafed5504f9 /bin/bash | 进入一个正在运行的容器 |
llvm 安装
bustub 环境依赖 clang 相关包。
安装 clang 相关包时遇到 "Unable to locate package" 错误。
clang 通常属于 LLVM 项目,特定版本的 clang 可能需要从 LLVM 官方仓库安装。
apt-get update
apt install -y wget software-properties-common
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 14
安装完成后,重新执行完成环境准备。
build_support/packages.sh
开发环境
-
调试使用gdb和打印日志
-
代码开发基于vim
-
自动补全插件使用 coc.nvim
-
代码格式化插件 vim-clang-format
-
文件搜索插件 ctrlp.vim
-
-
使用 coc 时,发现项目内的头文件没有被识别出来,这里采用最直接的方式,将指定的头文件目录加到bashrc中,即当前目录所有已include结尾的路径
export CPATH=$(find /<path>/cmu15445/bustub-wys -type d -name include | tr '\n' ':')
export CPLUS_INCLUDE_PATH=$(find /<path>/cmu15445/bustub-wys -type d -name include | tr '\n' ':')
当前 vim 配置,后面继续优化
let mapleader = " "
autocmd vimenter * colorscheme gruvbox
"autocmd vimenter * NERDTree
call plug#begin('~/.vim/plugged')
Plug 'morhetz/gruvbox'
Plug 'preservim/nerdtree'
Plug 'ctrlpvim/ctrlp.vim'
" Use release branch (recommend)
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'rhysd/vim-clang-format'
call plug#end()
set list
set bg=dark
color desert
set nu
set nocompatible
set tabstop=2
set softtabstop=2
set shiftwidth=2
set expandtab
set cursorline
set autoindent
set backspace=2
set ff=unix
syntax on
vnoremap kj <ESC>
inoremap kj <ESC>
set foldmethod=indent
set ignorecase
set visualbell
set list
nnoremap <Space>rc :e ~/.vim/vimrc<CR>
"nnoremap <F2> :set invpaste paste?<CR>
"imap <F2> <C-O>:set invpaste paste?<CR>
"set pastetoggle=<F2>
" 设置NerdTree
map <F3> :NERDTreeMirror<CR>
map <F3> :NERDTreeToggle<CR>
" use <tab> for trigger completion and navigate to the next complete item
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~ '\s'
endfunction
inoremap <silent><expr> <Tab>
\ pumvisible() ? "\<C-n>" :
\ <SID>check_back_space() ? "\<Tab>" :
\ coc#refresh()
" 跳转到定义
nmap <silent> gd <Plug>(coc-definition)
" 跳转到声明
nmap <silent> gD <Plug>(coc-declaration)
" 跳转到类型定义
nmap <silent> gy <Plug>(coc-type-definition)
" 跳转到实现
nmap <silent> gi <Plug>(coc-implementation)
" 跳转到引用
nmap <silent> gr <Plug>(coc-references)
"let g:clang_format#auto_format_on_insert_leave=1 "退出插入模式时自动格式化
"
"let g:clang_format#style_options = {
" \ "AccessModifierOffset" : -4,
" \ "AllowShortIfStatementsOnASingleLine" : "true",
" \ "AlwaysBreakTemplateDeclarations" : "true",
" \ "Standard" : "C++11"}
"
"" map to <Leader>cf in C++ code
"autocmd FileType c,cpp,objc nnoremap <buffer><Leader>cf :<C-u>ClangFormat<CR>
"autocmd FileType c,cpp,objc vnoremap <buffer><Leader>cf :ClangFormat<CR>
"" if you install vim-operator-user
"autocmd FileType c,cpp,objc map <buffer><Leader>x <Plug>(operator-clang-format)
"" Toggle auto formatting:
"" nmap <Leader>C :ClangFormatAutoToggle<CR>
" Use <Tab> and <S-Tab> to navigate the completion list
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
" Make <CR> auto-select the first completion item and notify coc.nvim to
" format on enter, <cr> could be remapped by other vim plugin
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
- 题目打包提交时,发现代码路径不是需要提交的文件,需要调整一下 build.make
Hyperloglog 理解
- Task1 实现的hyperloglog,实际上在通过前k位分桶,然后每个桶维护最大的左边开始连续的0的数量R[i],最后套公式计算期望的uniqie value数量
- Task2 实现的hyperloglog_prestore,是针对hyperloglog存储上有优化的版本。同样通过前k位分桶,但是每个桶维护最大的右边连续的0的数量R[i]。但是维护这个数量时,不是直接存储这个数字,而是将他的低4位bitset存在预先分配好内存的dense_bucket里,当他的超过4位时,将超出的位放到一个hash_map里,key是bucket_id,val是溢出的位的biset。最后,计算方法和hyperloglog一致
通过记录
小结
project0的卡点除了环境配置外,就是题目意思的理解不清楚,看了题目推荐的文章之后,想了一段时间才想明白它的意思。c++很多高级用法不熟悉,有的已经忘了,需要补习下。