diff --git a/.gitignore b/.gitignore index 1f3960b..a94b804 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ __pycache__ .vscode .env \~\$*.xlsx +node_modules diff --git a/README.md b/README.md index 4141e0b..aef2fa7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ +# linux笔记 * [system 系统 优化](./linux/system.md) * [user & group 用户和组](./linux/user_group.md) -* [markdown](./markdown.md) * [linux命令搜索网站](https://wangchujiang.com/linux-command/) ## shell编程 @@ -10,6 +10,7 @@ ./shellprogramming/README.md ``` + ## [cache](./cache.md) ## 操作系统 @@ -249,7 +250,9 @@ chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo "/swapfile none swap sw 0 0" >> /etc/fstab +# 0尽量不使用swap交换空间, 100积极得使用交换空间 0会OOM(out of memory). 10代表内存仅剩10%时,开始使用交换分区 echo "vm.swappiness=10" >> /etc/sysctl.conf +sudo sysctl -p ``` ## sysctl diff --git a/README_bundle_solution.md b/README_bundle_solution.md new file mode 100644 index 0000000..913d8a5 --- /dev/null +++ b/README_bundle_solution.md @@ -0,0 +1,188 @@ +# Git Bundle 增量同步完整解决方案 + +## 问题背景 + +你遇到的场景: +1. 分支 `inner` 基于 master 的 A0 节点,开发了 A1, A2, A3, A4 +2. 已经将 A1-A3 打包成 `bundle_A123` 给同事C +3. 同事B开发了B1并合并到master +4. 你将A4 rebase到B1后变成:A0 → B1 → A1' → A2' → A3' → A4' +5. 现在需要给同事C发送A4',但要避免重新传输A1', A2', A3' + +## 解决方案概述 + +**核心思路**:创建增量bundle,只包含A4'这个新提交,充分利用同事C已有的bundle_A123。 + +## 具体操作步骤 + +### 第一步:你的操作(创建增量bundle) + +```bash +# 1. 确保你在inner分支上 +git checkout inner + +# 2. 找到A3'的commit hash +git log --oneline -5 +# 假设A3'的hash是 abc123 + +# 3. 使用脚本创建增量bundle +./create_incremental_bundle.sh -b abc123 -t inner -c + +# 或者手动创建 +git bundle create bundle_A4_only.bundle abc123..inner +``` + +### 第二步:发送给同事C + +将生成的 `bundle_A4_only.bundle`(或压缩后的 `.gz` 文件)发送给同事C。 + +### 第三步:同事C的操作(应用增量bundle) + +```bash +# 方法1:使用提供的脚本(推荐) +./apply_incremental_bundle.sh bundle_A4_only.bundle + +# 方法2:手动操作 +# 2.1 首先确保已经应用了之前的bundle_A123 +git fetch bundle_A123.bundle refs/heads/inner:inner_base + +# 2.2 应用新的增量bundle +git fetch bundle_A4_only.bundle refs/heads/inner:inner_updated + +# 2.3 切换到更新后的分支 +git checkout inner_updated +``` + +## 提供的工具脚本 + +### 1. `create_incremental_bundle.sh` - 创建增量bundle + +**功能特点**: +- 自动验证提交点存在性 +- 显示将要打包的提交列表 +- 支持压缩输出 +- 提供详细的操作指导 + +**使用示例**: +```bash +# 基本用法 +./create_incremental_bundle.sh -b HEAD~1 + +# 指定目标分支和输出文件 +./create_incremental_bundle.sh -b abc123 -t inner -o my_bundle.bundle + +# 创建压缩的bundle +./create_incremental_bundle.sh -b abc123 -c +``` + +### 2. `apply_incremental_bundle.sh` - 应用增量bundle + +**功能特点**: +- 自动验证bundle完整性 +- 支持预览模式查看内容 +- 可创建新分支或更新现有分支 +- 自动处理压缩文件 + +**使用示例**: +```bash +# 基本用法 +./apply_incremental_bundle.sh bundle_A4_only.bundle + +# 预览bundle内容 +./apply_incremental_bundle.sh --preview bundle_A4_only.bundle + +# 创建新分支而不是更新现有分支 +./apply_incremental_bundle.sh -n bundle_A4_only.bundle +``` + +## 高级技巧 + +### 1. 使用Git标签标记关键点 + +```bash +# 在创建bundle_A123时打标签 +git tag -a sync_point_A123 A3_commit_hash -m "Sync point for bundle_A123" + +# 基于标签创建增量bundle +./create_incremental_bundle.sh -b sync_point_A123 +``` + +### 2. 验证bundle大小对比 + +```bash +# 创建完整bundle(对比用) +git bundle create bundle_full.bundle master..inner + +# 创建增量bundle +./create_incremental_bundle.sh -b A3_hash + +# 对比大小 +ls -lh *.bundle +``` + +### 3. 处理复杂的rebase情况 + +如果rebase后的A1', A2', A3'与原来的A1, A2, A3差异很大: + +```bash +# 方案1:基于共同祖先创建bundle +COMMON_ANCESTOR=$(git merge-base A3_original_hash A3_new_hash) +git bundle create bundle_from_common.bundle $COMMON_ANCESTOR..inner + +# 方案2:使用cherry-pick方式 +# 让同事C基于bundle_A123创建分支,然后应用A4' +git bundle create bundle_A4_cherry.bundle A4_hash^..A4_hash +``` + +## 故障排除 + +### 问题1:同事C应用bundle后出现冲突 +```bash +# 检查当前状态 +git status + +# 查看冲突的文件 +git diff + +# 解决冲突后继续 +git add . +git commit -m "Resolve conflicts from incremental bundle" +``` + +### 问题2:bundle验证失败 +```bash +# 重新创建bundle +git bundle create new_bundle.bundle base_commit..target_branch + +# 验证bundle +git bundle verify new_bundle.bundle +``` + +### 问题3:找不到基础提交点 +```bash +# 查看详细的提交历史 +git log --oneline --graph -20 + +# 或者使用reflog查找 +git reflog show inner +``` + +## 最佳实践建议 + +1. **记录同步点**:每次创建bundle时记录base commit hash +2. **使用描述性文件名**:包含日期、分支名和版本信息 +3. **验证操作**:在本地模拟同事的操作流程 +4. **备份重要分支**:在应用bundle前创建备份分支 +5. **压缩传输**:对于大文件使用压缩选项 +6. **文档化流程**:团队内部建立标准的bundle同步流程 + +## 总结 + +这个解决方案通过创建增量bundle,有效解决了rebase后避免重复传输的问题。关键优势: + +- ✅ **大幅减少传输大小**:只传输新的提交A4' +- ✅ **保持完整历史**:同事C可以完整重建分支历史 +- ✅ **操作简单**:提供自动化脚本,减少人为错误 +- ✅ **灵活性高**:支持多种应用方式和验证选项 + +通过这种方式,你可以高效地与内网同事同步代码,避免重复传输大量已同步的内容。 \ No newline at end of file diff --git a/_static/package.json b/_static/package.json new file mode 100644 index 0000000..20e103e --- /dev/null +++ b/_static/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "@mermaid-js/layout-elk": "^0.1.7", + "d3": "^7.9.0", + "mermaid": "^11.6.0" + } +} diff --git a/apply_incremental_bundle.sh b/apply_incremental_bundle.sh new file mode 100755 index 0000000..b3cc83d --- /dev/null +++ b/apply_incremental_bundle.sh @@ -0,0 +1,238 @@ +#!/bin/bash + +# Git Bundle 增量应用脚本 +# 用于应用增量bundle到本地仓库 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 打印带颜色的消息 +print_info() { + echo -e "${BLUE}ℹ️ $1${NC}" +} + +print_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +print_warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +print_error() { + echo -e "${RED}❌ $1${NC}" +} + +# 显示帮助信息 +show_help() { + echo "Git Bundle 增量应用脚本" + echo "" + echo "用法:" + echo " $0 [选项] BUNDLE_FILE" + echo "" + echo "选项:" + echo " -b, --branch BRANCH 目标分支名 (默认: 从bundle中推断)" + echo " -n, --new-branch 创建新分支而不是更新现有分支" + echo " -p, --preview 预览模式,只显示将要应用的提交" + echo " -h, --help 显示此帮助信息" + echo "" + echo "示例:" + echo " $0 bundle_inner_20241201_143022.bundle" + echo " $0 -b inner -n bundle_A4_only.bundle" + echo " $0 --preview bundle_incremental.bundle" + echo "" + echo "注意:" + echo " 在应用bundle之前,请确保你已经应用了之前的bundle_A123" +} + +# 默认值 +BUNDLE_FILE="" +TARGET_BRANCH="" +CREATE_NEW_BRANCH=false +PREVIEW_MODE=false + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case $1 in + -b|--branch) + TARGET_BRANCH="$2" + shift 2 + ;; + -n|--new-branch) + CREATE_NEW_BRANCH=true + shift + ;; + -p|--preview) + PREVIEW_MODE=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + -*) + print_error "未知参数: $1" + show_help + exit 1 + ;; + *) + if [[ -z "$BUNDLE_FILE" ]]; then + BUNDLE_FILE="$1" + else + print_error "只能指定一个bundle文件" + exit 1 + fi + shift + ;; + esac +done + +# 检查必需参数 +if [[ -z "$BUNDLE_FILE" ]]; then + print_error "必须指定bundle文件" + show_help + exit 1 +fi + +# 检查bundle文件是否存在 +if [[ ! -f "$BUNDLE_FILE" ]]; then + print_error "Bundle文件不存在: $BUNDLE_FILE" + exit 1 +fi + +# 解压bundle文件(如果是压缩的) +ORIGINAL_BUNDLE="$BUNDLE_FILE" +if [[ "$BUNDLE_FILE" == *.gz ]]; then + print_info "检测到压缩的bundle文件,正在解压..." + UNCOMPRESSED_FILE="${BUNDLE_FILE%.gz}" + if [[ ! -f "$UNCOMPRESSED_FILE" ]]; then + gunzip -k "$BUNDLE_FILE" + fi + BUNDLE_FILE="$UNCOMPRESSED_FILE" + print_success "解压完成: $BUNDLE_FILE" +fi + +print_info "开始处理bundle: $BUNDLE_FILE" + +# 验证bundle +print_info "正在验证bundle..." +if ! git bundle verify "$BUNDLE_FILE"; then + print_error "Bundle验证失败" + exit 1 +fi +print_success "Bundle验证通过" + +# 获取bundle中的分支信息 +print_info "Bundle中包含的分支:" +BUNDLE_HEADS=$(git bundle list-heads "$BUNDLE_FILE") +echo "$BUNDLE_HEADS" + +# 如果没有指定目标分支,尝试从bundle中推断 +if [[ -z "$TARGET_BRANCH" ]]; then + # 提取第一个分支名 + TARGET_BRANCH=$(echo "$BUNDLE_HEADS" | head -n1 | awk '{print $2}' | sed 's|refs/heads/||') + if [[ -z "$TARGET_BRANCH" ]]; then + print_error "无法从bundle中推断分支名,请使用 -b/--branch 指定" + exit 1 + fi + print_info "推断的目标分支: $TARGET_BRANCH" +fi + +# 预览模式 +if [[ "$PREVIEW_MODE" == true ]]; then + print_info "预览模式 - 显示bundle中的提交:" + + # 创建临时分支来查看提交 + TEMP_BRANCH="temp_preview_$(date +%s)" + git fetch "$BUNDLE_FILE" "refs/heads/$TARGET_BRANCH:$TEMP_BRANCH" + + echo + print_info "Bundle中的新提交:" + if git show-branch --current "$TEMP_BRANCH" 2>/dev/null | grep -q "\[$TEMP_BRANCH\]"; then + git log --oneline --graph "$TEMP_BRANCH" ^HEAD 2>/dev/null || git log --oneline "$TEMP_BRANCH" -10 + else + git log --oneline "$TEMP_BRANCH" -10 + fi + + # 清理临时分支 + git branch -D "$TEMP_BRANCH" + + echo + print_info "预览完成。要应用bundle,请重新运行脚本而不使用 --preview 选项" + exit 0 +fi + +# 检查当前状态 +if [[ -n "$(git status --porcelain)" ]]; then + print_warning "工作目录不干净,建议先提交或暂存更改" + echo "未提交的更改:" + git status --short + echo + read -p "是否继续? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + print_info "操作已取消" + exit 0 + fi +fi + +# 应用bundle +if [[ "$CREATE_NEW_BRANCH" == true ]]; then + # 创建新分支 + NEW_BRANCH_NAME="${TARGET_BRANCH}_$(date +%Y%m%d_%H%M%S)" + print_info "创建新分支: $NEW_BRANCH_NAME" + + git fetch "$BUNDLE_FILE" "refs/heads/$TARGET_BRANCH:$NEW_BRANCH_NAME" + git checkout "$NEW_BRANCH_NAME" + + print_success "成功创建并切换到新分支: $NEW_BRANCH_NAME" +else + # 更新现有分支或创建分支 + print_info "应用bundle到分支: $TARGET_BRANCH" + + # 检查分支是否存在 + if git show-ref --verify --quiet "refs/heads/$TARGET_BRANCH"; then + # 分支存在,更新它 + CURRENT_BRANCH=$(git branch --show-current) + + if [[ "$CURRENT_BRANCH" == "$TARGET_BRANCH" ]]; then + # 当前就在目标分支上 + git fetch "$BUNDLE_FILE" "refs/heads/$TARGET_BRANCH" + git merge FETCH_HEAD + else + # 在其他分支上,先切换 + git fetch "$BUNDLE_FILE" "refs/heads/$TARGET_BRANCH:$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + else + # 分支不存在,创建它 + git fetch "$BUNDLE_FILE" "refs/heads/$TARGET_BRANCH:$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + + print_success "成功应用bundle到分支: $TARGET_BRANCH" +fi + +# 显示应用后的状态 +echo +print_info "应用后的分支状态:" +git log --oneline --graph -5 + +echo +print_success "Bundle应用完成!" + +# 清理解压的文件(如果原文件是压缩的) +if [[ "$ORIGINAL_BUNDLE" != "$BUNDLE_FILE" && "$ORIGINAL_BUNDLE" == *.gz ]]; then + read -p "是否删除解压后的bundle文件 $BUNDLE_FILE? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + rm "$BUNDLE_FILE" + print_info "已删除解压后的文件: $BUNDLE_FILE" + fi +fi \ No newline at end of file diff --git a/articles.md b/articles.md new file mode 100644 index 0000000..1d380c7 --- /dev/null +++ b/articles.md @@ -0,0 +1,4 @@ +# 文章 +```{toctree} +./articles/多个列表组合的链表.md +``` diff --git "a/articles/\345\244\232\344\270\252\345\210\227\350\241\250\347\273\204\345\220\210\347\232\204\351\223\276\350\241\250.md" "b/articles/\345\244\232\344\270\252\345\210\227\350\241\250\347\273\204\345\220\210\347\232\204\351\223\276\350\241\250.md" new file mode 100644 index 0000000..92c9d3e --- /dev/null +++ "b/articles/\345\244\232\344\270\252\345\210\227\350\241\250\347\273\204\345\220\210\347\232\204\351\223\276\350\241\250.md" @@ -0,0 +1,98 @@ +# 多个数组组合的链表 +## 背景 +业务开发中总是会遇到队列数据. +比如超大规模电商平台, 每秒上千次交易. + * 如果放在链表,每次的插入,释放都要处理内存申请释放,速度很慢 + * 如果放入一个数组, 不断地rpush, lpop, 那每次pop时都会导致数组重写,速度比较差. + * 如果放入一个固定数组改指针, 那当处理不过来时, 数据超过数组大小时, 程序就会崩溃. + * 如果放入动态长度的数组(比如C++的vector), 当插入数量超过数组的容量时, 整个数组的拷贝会导致程序卡顿 + +## 其他人的思路 +* [redis的list就是用这个思路实现的](https://zhuanlan.zhihu.com/p/102422311) +```python +""" +根据redis源码用python实现的伪代码 +""" +def quicklistCreateNode(): + """我发现这个Create的nodesize很小,实际内容是在__quicklistCompressNode的时候,申请到了内存地址保存在node的entry的""" + pass + +class quicklistEntry: + """每个保存的元素""" + quicklist + quicklistnode + +class Node: + """包含最多65536个Entry""" + pre: Node + next: Node + entry: bytes # 真正数据对应的字节地址 + entries: List[quicklistEntry] # python直接用对象 + + def lpappend(self, entry): + pass + +class QuickList: + """包含Node的链表""" + nodes: List[Node] + + def push_tail(self, entry): + if self.nodes[-1].allow_insert(): + # quicklistNodeUpdateSz + self.nodes[-1].append(entry) + else: + new_node = quicklistCreateNode() + self.nodes.append(new_node) + new_node.append(entry) +``` + + +## 解决思路 +集合固定列表改指针和动态长度的列表的优点, 用多个数组加指针来保存数据 +``` +array1 = [a, b, c, d] +array1.next = &array2 +array2 = [d, e, f, g] +array2.next = null +``` + +1. 创建数据结构 +``` +struct Order {} +struct SubOrderArray { + prev: *SubOrderArray + next: *SubOrderArray + orders: *Array[Order] + array_size: int +} +struct State { + current_array: &SubOrderArray + current_order: &Order + last_array: &SubOrderArray +} +``` + +2. 当来了一笔新订单时 + * 如果`state.last_array`没满,直接插入数据到last_array + * 如果`state.last_array`满了 + 1. 申请新的new_array(长度可以是`state.array_size`, `state.array_size *= 1.3`) + 2. 把新的new_array插入原来的链表 + ``` + state -> last_array->next = new_array; + new_array.prev = state.last_array; + state.last_array = new_array + ``` + 3. 把order插入new_array + +3. 同理,当有个order处理完毕后 + * 如果order所在的array里还有数据, 直接修改state.current_order + * 如果order所在的array里没有数据库 + 1. 释放satte的current_array, state.array_size /= 2 + 2. 修改state的current_array和current_order + 3. 修改state.current_array.prev为null + +## 优点 +1. 当电商收到大量订单时, 内存是一次性申请长的array. 避免频繁申请内存 +2. 当后台处理订单时, 大部分order都在一个array里, 有cache优势 +3. 每次处理的数据都是在连续数组, 预取也方便 +4. 释放支持一次性释放 diff --git a/baserc b/baserc new file mode 100644 index 0000000..f2b2572 --- /dev/null +++ b/baserc @@ -0,0 +1,40 @@ +# 这里zshrc bashrc都支持的特性 +# 快捷操作 +export PYTHONBREAKPOINT=ipdb.set_trace +alias l='ls --color=auto' +alias ll='ls -al --color=auto' +alias ls="ls --color=auto" +alias mytree="tree -L 2 -d -I 'node_modules'" +alias py="ipython3" + + +function settitle() { + echo -ne "\033]0;${1}\007" +} + +export TLDR_PAGES_SOURCE_LOCATION=http://tldr.ramwin.com/pages/ +export TLDR_PAGES_SOURCE_LOCATION="file://"$HOME"/github/other/tldr/pages/" + +export PATH=\ +/Library/PostgreSQL/17/bin/\ +:$HOME/redis/src/\ +:$HOME/github/other/llvm-project/build/bin/\ +:$HOME/.local/bin/\ +:$HOME/venv/bin\ +:$HOME/sbt/bin\ +:$HOME/node/bin\ +:$HOME/shims\ +:$HOME/.local/bin/\ +:$HOME/bin/\ +:$HOME/github/python/python-reference/script/\ +:$HOME/github/linux-reference/script/\ +:$HOME/node_modules/bin/\ +:$HOME/github/secret/\ +:/usr/local/java/bin/\ +:/usr/local/eclipse/\ +:/usr/local/go/bin/\ +:/usr/local/go/bin/\ +:/usr/node/bin/\ +:/home/wangx/.pyenv/bin/\ +:/home/wangx/gh/bin/\ +:$PATH diff --git a/bashrc b/bashrc index 80eafb8..9b0118b 100644 --- a/bashrc +++ b/bashrc @@ -1,14 +1,16 @@ +source $HOME/github/linux-reference/baserc + # 用来在windows目录下用windows的git -cd() { - builtin cd "$1" - current_path=`realpath .` - if [[ $current_path == /mnt/d/* ]] - then - alias 'git="git.exe"' - else - alias git="git" - fi -} +# cd() { +# builtin cd "$1" +# current_path=`pwd` +# if [[ $current_path == /mnt/d/* ]] +# then +# alias 'git="git.exe"' +# else +# alias git="git" +# fi +# } export TLDR_CACHE_ENABLED=1 export TLDR_CACHE_MAX_AGE=24 @@ -50,52 +52,23 @@ function wxj(){ echo '---------------------输出完成----------------------' } -# export TERM="xterm-color" -# export CLICOLOR=1 -# export LSCOLORS=GxFxCxDxBxegedabagaced +# export TERM="xterm-256color" # 不然wsl下visidata会没有颜色 +export CLICOLOR=1 +export LSCOLORS=GxFxCxDxBxegedabagaced PYENV_ROOT="$HOME/.pyenv" -PATH=\ -:/home/wangx/venv/bin\ -:/home/wangx/node/bin\ -:$PYENV_ROOT/shims\ -:/home/wangx/bin/\ -:/home/wangx/github/python-reference/script/\ -:/home/wangx/github/linux-reference/script/\ -:/home/wangx/node_modules/bin/\ -:/home/wangx/github/secret/\ -:/usr/local/java/bin/\ -:/usr/local/eclipse/\ -:/usr/local/go/bin/\ -:/usr/local/go/bin/\ -:/usr/node/bin/\ -:/home/wangx/.pyenv/bin/\ -:/home/wangx/gh/bin/\ -:$PATH if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)" fi export NODE_PATH="${HOME}/node/lib/node_modules" -# 快捷操作 -alias l='ls' -alias ll='ls -al' -alias mytree="tree -L 2 -d -I 'node_modules'" -alias py="ipython" - # 目录快捷方式 alias github='cd ~/github' -alias work='cd ~/github/duishang' -alias lib='cd /usr/local/lib/python3.6/*-packages/' - # python alias pep='pep8 --max-line-length=120' alias gitflake='git status -s | grep .py | xargs flake8' # xset m 0 1 -function settitle() { - echo -ne "\033]0;${1}\007" -} # django alias dshell="python manage.py shell" @@ -105,20 +78,20 @@ export CLICOLOR=1 # settitle coding export LANGUAGE='en_US.UTF-8 git' export VISUAL="vim" -export PYTHONBREAKPOINT=ipdb.set_trace alias myfind="find . -not -path '*/site-packages/*' -not -path '*/node_modules/*'" +# alias bat="batcat" -PS1='[\[\e[37m\]#\##\[\e[01;32m\]\u@\[\e[00;31m\]$HOSTNAME:\W]\$\[\e[m\]' +# PS1='[\[\e[37m\]#\##\[\e[01;32m\]\u@\[\e[00;31m\]$HOSTNAME:\W]\$\[\e[m\]' # \[\e[37m\] 白色 -PS1='[\[\e[37m\]#\[\e[00;33m\]\#\[\e[37m\]#\[\e[01;32m\]\u\[\e[36m\]@\[\e[00;31m\]$HOSTNAME:\[\e[34m\]\W\[\e[37m\]] \[\e[m\]' +# PS1='[\[\e[37m\]#\[\e[00;33m\]\#\[\e[37m\]#\[\e[01;32m\]\u\[\e[36m\]@\[\e[00;31m\]$HOSTNAME:\[\e[34m\]\W\[\e[37m\]] \[\e[m\]' # 添加git分支显示 parse_git_branch() { - git branch 2> /dev/null | grep -v '* master' | grep -v '* main' | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' + show_branch.py + # git branch --show-current 2>/dev/null + # git branch 2> /dev/null | grep -v '* master' | grep -v '* main' | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/' } -PS1="[\[\e[37m\]#\[\e[00;33m\]\#\[\e[37m\]#\[\e[01;32m\]\u\[\e[36m\]@\[\e[00;31m\]$HOSTNAME:\[\033[32m\]\W\[\033[33m\]\$(parse_git_branch)\[\033[00m\]\[\e[37m\]] $ " +PS1="[\[\e[37m\]#\[\e[00;33m\]\#\[\e[37m\]#\[\e[01;32m\]\u\[\e[36m\]@\[\e[00;31m\]$HOSTNAME:\[\033[32m\]\W\[\033[33m\]\$(parse_git_branch)\[\033[00m\]\[\e[37m\] $ " -export TLDR_PAGES_SOURCE_LOCATION=http://tldr.ramwin.com/pages/ -export TLDR_PAGES_SOURCE_LOCATION="file:///home/wangx/github/tldr/pages/" # -F 允许超过一屏幕时才成less export LESS="-R-F" @@ -132,4 +105,8 @@ export HATCH_INDEX_USER="__token__" export CMAKE_CXX_COMPILER=clang++ export CMAKE_C_COMPILER=clang -export PYTHONPATH="/home/wangx/venv/lib/python3.12/site-packages" + +tail () { command tail -n 20 "$@"; } +head () { command head -n 20 "$@"; } + +set -o history # 记录报错的命令 diff --git a/bundle_solution.md b/bundle_solution.md new file mode 100644 index 0000000..b98aff1 --- /dev/null +++ b/bundle_solution.md @@ -0,0 +1,111 @@ +# Git Bundle 增量同步解决方案 + +## 问题描述 +- 分支inner基于master节点A0,开发了A1, A2, A3, A4 +- 已经将A1到A3打包成bundle_A123给同事C +- 同事B开发了B1并合并到master +- 将A4 rebase到B1后变成A1', A2', A3', A4' +- 需要将A4'发给同事C,但要避免重新传输A1', A2', A3' + +## 解决方案:增量Bundle策略 + +### 方案1:仅打包A4'(推荐) + +```bash +# 1. 在你的机器上,假设当前在inner分支上 +# 找到A3'的commit hash +git log --oneline -n 5 + +# 2. 只打包A4'这一个提交(假设A3'的hash是abc123) +git bundle create bundle_A4_only.bundle abc123..HEAD + +# 3. 将bundle_A4_only.bundle发送给同事C +``` + +### 同事C的操作流程: + +```bash +# 1. 首先应用之前的bundle_A123(如果还没有应用) +git fetch bundle_A123.bundle refs/heads/inner:inner_old +git checkout inner_old + +# 2. 应用新的增量bundle +git fetch bundle_A4_only.bundle refs/heads/inner:inner_new + +# 3. 检查差异并合并 +git log inner_old..inner_new --oneline +git checkout inner_new +``` + +### 方案2:基于已知点的增量bundle + +如果同事C已经有了A1, A2, A3的内容,可以: + +```bash +# 在你的机器上,创建从A3'到A4'的bundle +# 假设A3的原始hash是def456 +git bundle create bundle_A4_incremental.bundle def456..HEAD +``` + +### 方案3:使用--since参数 + +```bash +# 基于时间的增量bundle(如果知道A3的提交时间) +git bundle create bundle_recent.bundle --since="2024-01-01" HEAD +``` + +## 验证Bundle内容 + +```bash +# 查看bundle包含的内容 +git bundle list-heads bundle_A4_only.bundle +git bundle verify bundle_A4_only.bundle + +# 查看bundle的大小 +ls -lh *.bundle +``` + +## 最佳实践建议 + +1. **记录提交点**:每次创建bundle时记录base commit,方便后续增量操作 +2. **使用标签**:在关键节点打标签,便于引用 +3. **测试验证**:在本地模拟同事C的操作流程进行验证 + +## 示例脚本 + +```bash +#!/bin/bash +# create_incremental_bundle.sh + +# 参数检查 +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 abc123 inner" + exit 1 +fi + +BASE_COMMIT=$1 +TARGET_BRANCH=$2 +BUNDLE_NAME="bundle_incremental_$(date +%Y%m%d_%H%M%S).bundle" + +# 创建增量bundle +git bundle create "$BUNDLE_NAME" "$BASE_COMMIT..$TARGET_BRANCH" + +# 验证bundle +if git bundle verify "$BUNDLE_NAME"; then + echo "✅ Bundle created successfully: $BUNDLE_NAME" + echo "📦 Bundle size: $(ls -lh "$BUNDLE_NAME" | awk '{print $5}')" + echo "📋 Bundle contents:" + git bundle list-heads "$BUNDLE_NAME" +else + echo "❌ Bundle verification failed" + exit 1 +fi +``` + +## 注意事项 + +1. 确保base_commit在同事C那边已经存在 +2. 如果A1', A2', A3'与原来的A1, A2, A3内容完全不同,增量bundle可能仍然很大 +3. 考虑使用Git的`--thin`选项来进一步减小bundle大小 +4. 建议在传输前压缩bundle文件 \ No newline at end of file diff --git a/cache.md b/cache.md index 2fe14fa..fd2a60c 100644 --- a/cache.md +++ b/cache.md @@ -9,13 +9,13 @@ # direct memory mapping 会导致间断访问时,遇到conflict miss -![物理实现](./cache/direct-mapping-物理实现.png) +![物理实现](./cache/direct-mapping.png) # [associative mapping](https://www.youtube.com/watch?v=uwnsMaH-iV0&list=PLBlnK6fEyqRgLLlzdgiTUKULKJPYc0A4q&index=14) P.A.bits只分成了tag和line offset. 每个block都会被分配到任意的cache line. * 优点: 不会有conflict miss * 缺点: 查看数据的时候需要遍历所有的cache line -![物理实现](./cache/associative-maaping-物理实现.png) +![物理实现](./cache/associative-maaping.png) # [set associative mapping](https://www.youtube.com/watch?v=KhAh6thw_TI&list=PLBlnK6fEyqRgLLlzdgiTUKULKJPYc0A4q&index=17) 物理实现 diff --git a/cache/associative-maaping.png b/cache/associative-maaping.png new file mode 100644 index 0000000..c4bae37 Binary files /dev/null and b/cache/associative-maaping.png differ diff --git a/cache/direct-mapping.png b/cache/direct-mapping.png new file mode 100644 index 0000000..62fd5ef Binary files /dev/null and b/cache/direct-mapping.png differ diff --git a/chisel/HelloWorld.java b/chisel/HelloWorld.java new file mode 100644 index 0000000..23f215a --- /dev/null +++ b/chisel/HelloWorld.java @@ -0,0 +1,3 @@ +object HelloScala extends App { + println("Hello Chisel World!") +} diff --git a/conf.py b/conf.py index 1ed7d13..9e23590 100644 --- a/conf.py +++ b/conf.py @@ -18,11 +18,17 @@ "sphinx_design", "sphinx.ext.todo", "sphinx.ext.autodoc", - "sphinxmermaid", + "sphinxcontrib.mermaid", ] templates_path = ['_templates'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = [ + '_build', + '.DS_Store', + '.git', + 'Thumbs.db', + "software/lz4/abc/directory/*.md", + ] language = 'zh_CN' @@ -32,16 +38,35 @@ html_theme = 'sphinx_rtd_theme' html_static_path = ['_static'] source_suffix = { - '.rst': 'restructuredtext', - '.md': 'markdown', + ".rst": "restructuredtext", + ".md": "markdown", } -myst_heading_anchors = 4 myst_enable_extensions = [ + "attrs_inline", "colon_fence", + "strikethrough", "tasklist", ] -suppress_warnings = ["myst.header", "myst.xref_missing"] +myst_heading_anchors = 7 html_css_files = [ "custom.css" ] todo_include_todos = True +latex_use_xindy = True +smartquotes = True +sphinxmermaid_mermaid_init = { + 'theme': 'base', + 'themeVariables': { + 'fontSize': '40px', + } +} +suppress_warnings = [ + "myst.header", + "myst.xref_missing", + "myst.not_included", + "toc.not_included", +] +mermaid_version = "11.2.0" +mermaid_use_local = "/_static/node_modules/mermaid/dist/mermaid.esm.min.mjs" +mermaid_elk_use_local = "/_static/node_modules/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs" +d3_use_local = "/_static/node_modules/d3/dist/d3.min.js" diff --git a/create_incremental_bundle.sh b/create_incremental_bundle.sh new file mode 100755 index 0000000..21e348a --- /dev/null +++ b/create_incremental_bundle.sh @@ -0,0 +1,190 @@ +#!/bin/bash + +# Git Bundle 增量同步脚本 +# 用于解决rebase后的增量同步问题 + +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 打印带颜色的消息 +print_info() { + echo -e "${BLUE}ℹ️ $1${NC}" +} + +print_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +print_warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +print_error() { + echo -e "${RED}❌ $1${NC}" +} + +# 显示帮助信息 +show_help() { + echo "Git Bundle 增量同步脚本" + echo "" + echo "用法:" + echo " $0 [选项]" + echo "" + echo "选项:" + echo " -b, --base COMMIT 基础提交点 (必需)" + echo " -t, --target BRANCH 目标分支 (默认: 当前分支)" + echo " -o, --output FILE 输出文件名 (默认: 自动生成)" + echo " -c, --compress 压缩bundle文件" + echo " -h, --help 显示此帮助信息" + echo "" + echo "示例:" + echo " $0 -b abc123 -t inner" + echo " $0 --base HEAD~1 --output my_bundle.bundle --compress" + echo "" + echo "场景说明:" + echo " 当你rebase了分支后,想要只发送新的提交给同事," + echo " 而不是重新发送整个分支的内容。" +} + +# 默认值 +BASE_COMMIT="" +TARGET_BRANCH="" +OUTPUT_FILE="" +COMPRESS=false + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case $1 in + -b|--base) + BASE_COMMIT="$2" + shift 2 + ;; + -t|--target) + TARGET_BRANCH="$2" + shift 2 + ;; + -o|--output) + OUTPUT_FILE="$2" + shift 2 + ;; + -c|--compress) + COMPRESS=true + shift + ;; + -h|--help) + show_help + exit 0 + ;; + *) + print_error "未知参数: $1" + show_help + exit 1 + ;; + esac +done + +# 检查必需参数 +if [[ -z "$BASE_COMMIT" ]]; then + print_error "必须指定基础提交点 (-b/--base)" + show_help + exit 1 +fi + +# 获取当前分支作为默认目标分支 +if [[ -z "$TARGET_BRANCH" ]]; then + TARGET_BRANCH=$(git branch --show-current) + if [[ -z "$TARGET_BRANCH" ]]; then + print_error "无法确定当前分支,请使用 -t/--target 指定目标分支" + exit 1 + fi +fi + +# 生成默认输出文件名 +if [[ -z "$OUTPUT_FILE" ]]; then + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + OUTPUT_FILE="bundle_${TARGET_BRANCH}_${TIMESTAMP}.bundle" +fi + +print_info "开始创建增量bundle..." +print_info "基础提交: $BASE_COMMIT" +print_info "目标分支: $TARGET_BRANCH" +print_info "输出文件: $OUTPUT_FILE" + +# 验证基础提交是否存在 +if ! git rev-parse --verify "$BASE_COMMIT" >/dev/null 2>&1; then + print_error "基础提交 '$BASE_COMMIT' 不存在" + exit 1 +fi + +# 验证目标分支是否存在 +if ! git rev-parse --verify "$TARGET_BRANCH" >/dev/null 2>&1; then + print_error "目标分支 '$TARGET_BRANCH' 不存在" + exit 1 +fi + +# 检查是否有新的提交 +COMMIT_COUNT=$(git rev-list --count "$BASE_COMMIT..$TARGET_BRANCH") +if [[ "$COMMIT_COUNT" -eq 0 ]]; then + print_warning "从 '$BASE_COMMIT' 到 '$TARGET_BRANCH' 没有新的提交" + exit 0 +fi + +print_info "发现 $COMMIT_COUNT 个新提交:" +git log --oneline "$BASE_COMMIT..$TARGET_BRANCH" +echo + +# 创建bundle +print_info "正在创建bundle..." +if git bundle create "$OUTPUT_FILE" "$BASE_COMMIT..$TARGET_BRANCH"; then + print_success "Bundle创建成功: $OUTPUT_FILE" +else + print_error "Bundle创建失败" + exit 1 +fi + +# 验证bundle +print_info "正在验证bundle..." +if git bundle verify "$OUTPUT_FILE"; then + print_success "Bundle验证通过" +else + print_error "Bundle验证失败" + exit 1 +fi + +# 显示bundle信息 +BUNDLE_SIZE=$(ls -lh "$OUTPUT_FILE" | awk '{print $5}') +print_info "Bundle大小: $BUNDLE_SIZE" + +print_info "Bundle包含的分支:" +git bundle list-heads "$OUTPUT_FILE" + +# 压缩bundle (如果需要) +if [[ "$COMPRESS" == true ]]; then + print_info "正在压缩bundle..." + if command -v gzip >/dev/null 2>&1; then + gzip -k "$OUTPUT_FILE" + COMPRESSED_FILE="${OUTPUT_FILE}.gz" + COMPRESSED_SIZE=$(ls -lh "$COMPRESSED_FILE" | awk '{print $5}') + print_success "压缩完成: $COMPRESSED_FILE (大小: $COMPRESSED_SIZE)" + else + print_warning "gzip命令不可用,跳过压缩" + fi +fi + +echo +print_success "增量bundle创建完成!" +echo +print_info "接下来的步骤:" +echo "1. 将 $OUTPUT_FILE 发送给同事C" +echo "2. 同事C执行以下命令应用bundle:" +echo " git fetch $OUTPUT_FILE refs/heads/$TARGET_BRANCH:${TARGET_BRANCH}_new" +echo " git checkout ${TARGET_BRANCH}_new" +echo +print_info "或者同事C可以使用以下命令直接更新现有分支:" +echo " git fetch $OUTPUT_FILE refs/heads/$TARGET_BRANCH:$TARGET_BRANCH" \ No newline at end of file diff --git a/database.md b/database.md index 618f296..23a06ce 100644 --- a/database.md +++ b/database.md @@ -3,11 +3,9 @@ ./postgresql.md ./redis/redis.md ./mysql/README.md -./mongodb.md +./database/mongodb.md ``` -[集群搭建参考](./redis-cluster/README.md) - ## [mongodb](./mongodb.md) ## SQL diff --git a/database/mongo.md b/database/mongo.md deleted file mode 100644 index 1b8a037..0000000 --- a/database/mongo.md +++ /dev/null @@ -1,13 +0,0 @@ -#### Xiang Wang @ 2017-03-13 15:06:08 - -# 启动服务 -``` - # 直接启动 - docker run --name mongoserver -p 27017:27017 -d mongo - # 暴露端口 -``` - -# 连接mongodb -``` - docker run -ti --link mongoserver:mongo --rm mongo sh -c 'exec mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test"' -``` diff --git a/mongodb.md b/database/mongodb.md similarity index 75% rename from mongodb.md rename to database/mongodb.md index 0d28ab2..8c56fba 100644 --- a/mongodb.md +++ b/database/mongodb.md @@ -1,7 +1,14 @@ # mongodb ## 启动与退出 - docker pull mongo - docker run --name some-mogo -d -p 27017:27017 -p 28017:28017 mongo:tag +``` +docker pull mongo +docker run --name some-mogo -d -p 27017:27017 -p 28017:28017 mongo:tag +docker run --name mongoserver -p 27017:27017 -d mongo +``` +* 链接使用 +``` + docker run -ti --link mongoserver:mongo --rm mongo sh -c 'exec mongo "$MONGO_PORT_27017_TCP_ADDR:$MONGO_PORT_27017_TCP_PORT/test"' +``` ## python相关 [pymongo](https://docs.mongodb.org/getting-started/python/client/) diff --git a/database/other.md b/database/other.md deleted file mode 100644 index 5dd5b9b..0000000 --- a/database/other.md +++ /dev/null @@ -1,4 +0,0 @@ -#### Xiang Wang @ 2016-07-18 10:03:16 - -* ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) - 1. 重启mysql服务,这是因为/var/run/mysql/mysqld.sock文件被删除了,重启mysql的话会重新创建这个文件 diff --git a/database/settings.md b/database/settings.md deleted file mode 100644 index 9bb7f5e..0000000 --- a/database/settings.md +++ /dev/null @@ -1,5 +0,0 @@ -# 基础设置 -* .show # 查看基础设置 -* .header on -* .mode column -* .timer on diff --git a/etc/docker/daemon.json b/etc/docker/daemon.json new file mode 100644 index 0000000..8fc8aa8 --- /dev/null +++ b/etc/docker/daemon.json @@ -0,0 +1,8 @@ +{ + "iptables" : false, + "proxies": { + "http-proxy": "socks5://127.0.0.1:1080", + "https-proxy": "socks5://127.0.0.1:1080", + "no-proxy": "http://*.ramwin.com" + } +} diff --git a/etc/sysctl.conf b/etc/sysctl.conf new file mode 100644 index 0000000..c92f643 --- /dev/null +++ b/etc/sysctl.conf @@ -0,0 +1,8 @@ +# https://blog.csdn.net/weixin_44410537/article/details/98449706 +# dirty page cache达到50%以后,系统开始写入磁盘,此时仍然可以异步写入 +# 为什么只看dirty, 因为clean的直接删除就可以,速度快 +vm.dirty_background_ratio=50 +# dirty page cache达到70%以后, 不允许异步写入 +vm.dirty_ratio=70 +# 最多允许等待1分钟才写入磁盘 +vm.dirty_expire_centisecs = 6000 diff --git a/git.md b/git.md index 22b0ffe..104fef3 100644 --- a/git.md +++ b/git.md @@ -467,6 +467,7 @@ git log 是按照时间顺序往前找的 #### [格式化 PRETTY FORMATS](https://git-scm.com/docs/git-log#_pretty_formats) * `git log --graph --pretty=format:"%Cblue%h %Cred%s %Creset----%cn @ %ad" --date=format:'%Y-%m-%d %H:%M' %d` +* `--format="%H"`: 格式方法 * %h %H 简短/完整的哈希字符串 * %d %D ref的name, %D代表了不用括号括起来 * %an author name 作者名字 diff --git a/gitconfig b/gitconfig index 4091d8c..bc5a6f0 100644 --- a/gitconfig +++ b/gitconfig @@ -2,14 +2,21 @@ co = checkout lg = log --graph --pretty=format:\"%Cgreen%h %Cred%s %Creset----%C(yellow)%an %Creset@ %ad %C(green)%d\" --date=format:\"%Y-%m-%d %H:%M\" mt = mergetool - rb = "rebase --continue" + rb = "rebase" + rbc = "rebase --continue" + last = log -1 HEAD + cp = cherry-pick + cpc = "cherry-pick --continue" + release = "!sh -c \"git commit -m 'release $1'\"" [branch "master"] remote = origin merge = refs/heads/master [core] - bigFileThreshold = 1M + bigFileThreshold = 50M excludesfile = ~/.gitignore_global quotepath = false +[diff] + toll = vimdiff [filter "lfs"] clean = git-lfs clean -- %f smudge = git-lfs smudge -- %f @@ -35,6 +42,7 @@ [diff] toll = vimdiff wordRegex = "[^[:space:],;=]+" + tool = vimdiff [checkout] workers = 15 [color] diff --git a/gitignore_global b/gitignore_global index b4be7a8..fbd72a0 100644 --- a/gitignore_global +++ b/gitignore_global @@ -179,3 +179,21 @@ time.csv _build *.db .npmrc +*.tmp + +## 超链接 +django_commands +duration +test.* +wangx.sh +~$* +time.csv +.vite +node_modules +run_test.sh +test.sh +log +tmp +stdout.log\.[0-9]* +stderr.log\.[0-9]* +.DS_Store diff --git a/index.rst b/index.rst index 71f6fdf..6e01677 100644 --- a/index.rst +++ b/index.rst @@ -10,11 +10,15 @@ Welcome to linux reference's documentation! :maxdepth: 4 :caption: Contents: + ./计算机组成原理.md ./software.md ./database.md ./restructed/restructed语法.rst ./README.md ./hardware.md + ./linux/signal.md + ./mac.md + ./articles.md Indices and tables diff --git a/linux/signal.md b/linux/signal.md new file mode 100644 index 0000000..a9cc66d --- /dev/null +++ b/linux/signal.md @@ -0,0 +1,8 @@ +## signal +信号 + +* SIGINT +ctrl + c 会导致程序中止 + +* SIGTERM +让程序优雅中止 diff --git a/mac.md b/mac.md new file mode 100644 index 0000000..01d114d --- /dev/null +++ b/mac.md @@ -0,0 +1,14 @@ +# MAC + +## 系统 +* 打开 spotlight windows+space +* 锁屏 ^ + shift + power + +## 命令行 +* 行首 ^ a +* 行尾 ^ e + +## brew +``` +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +``` diff --git a/mac/proxy.sh b/mac/proxy.sh new file mode 100644 index 0000000..beecad0 --- /dev/null +++ b/mac/proxy.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Xiang Wang(ramwin@qq.com) + +export https_proxy=http://localhost:1087 +export HTTP_PROXY=http://localhost:1087 +export HTTPS_PROXY=http://localhost:1087 +export no_http_proxy="localhost;ramwin.com;*.cn" +export no_https_proxy="localhost;ramwin.com;*.cn" diff --git a/mac/shadowsocks.md b/mac/shadowsocks.md new file mode 100644 index 0000000..52f427e --- /dev/null +++ b/mac/shadowsocks.md @@ -0,0 +1 @@ +https://github.com/shadowsocks/ShadowsocksX-NG/releases/download/v1.10.3/ShadowsocksX-NG.dmg diff --git a/mac/shortcut.md b/mac/shortcut.md deleted file mode 100644 index b97ad55..0000000 --- a/mac/shortcut.md +++ /dev/null @@ -1,9 +0,0 @@ -#### Xiang Wang @ 2016-08-19 12:33:41 - -## 系统 -* 打开 spotlight windows+space -* 锁屏 ^ + shift + power - -## 命令行 -* 行首 ^ a -* 行尾 ^ e diff --git "a/mac/software\350\275\257\344\273\266\345\256\211\350\243\205\345\215\270\350\275\275brew.md" "b/mac/software\350\275\257\344\273\266\345\256\211\350\243\205\345\215\270\350\275\275brew.md" deleted file mode 100644 index 136ae19..0000000 --- "a/mac/software\350\275\257\344\273\266\345\256\211\350\243\205\345\215\270\350\275\275brew.md" +++ /dev/null @@ -1,3 +0,0 @@ -#### Xiang Wang @ 2016-08-15 14:37:49 - -/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" diff --git a/make.bat b/make.bat deleted file mode 100644 index 32bb245..0000000 --- a/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=. -set BUILDDIR=_build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/markdown.md b/markdown.md index ff02060..d159177 100644 --- a/markdown.md +++ b/markdown.md @@ -1,15 +1,16 @@ -# 标题1 用 \# -## 标题2 用 \#\# -### 标题3 用 \#\#\# +# markdown语法 +## 标题1 用 \# +### 标题2 用 \#\# +#### 标题3 用 \#\#\# -# 链接 -## 普通链接 +## 链接 +### 普通链接 [链接](http://www.ramwin.com) \[Title\](Url) -## 图片 +### 图片 ![图片](http://mouapp.com/Mou_128.png) 图片的话就是链接前面加 ! -# 字体 +## 字体 **加粗** `**** ` *斜体* `**` ++万恶++ `++++` @@ -18,19 +19,19 @@ 换行符 两个空格 > 引用 `> 引用` -# 格式 -## 无序列表 +## 格式 +### 无序列表 * 列表1 * 第二个 -## 有序列表 +### 有序列表 1. 有序列表 `1. ` 2. 有序列表2 `2. ` -## 内嵌代码 `用 tab ` +### 内嵌代码 `用 tab ` !/usrbin/env python3 import this` -### 指定代码格式 +#### 指定代码格式 ```javascript // javascript function test() { @@ -44,13 +45,13 @@ } ``` -### 一点点代码 +#### 一点点代码 ``` import this ``` -# 其他 +## 其他 分割线 `***` *** diff --git a/mysql/README.md b/mysql/README.md index 69672c6..36e3fdb 100644 --- a/mysql/README.md +++ b/mysql/README.md @@ -518,3 +518,7 @@ DESC LIMIT 20; [fetching-Spatial-data]: https://dev.mysql.com/doc/refman/8.0/en/fetching-spatial-data.html [json-type-url]: https://dev.mysql.com/doc/refman/8.0/en/json.html + +## 问题定位 +* ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) + 1. 重启mysql服务,这是因为/var/run/mysql/mysqld.sock文件被删除了,重启mysql的话会重新创建这个文件 diff --git a/mysql/mysqldump/mysql_to_postgres.sh b/mysql/mysqldump/mysql_to_postgres.sh new file mode 100644 index 0000000..86c061a --- /dev/null +++ b/mysql/mysqldump/mysql_to_postgres.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +mysqldump \ + -u wangx \ + --set-gtid-purged=OFF \ + --column-statistics=0 \ + --result-file result.sql \ + --lock-tables=False \ + --skip-add-locks \ + --skip-quote-names \ + --net-buffer-length=32k \ + employees departments; diff --git a/nfs.md b/nfs.md index 3c37874..c217b36 100644 --- a/nfs.md +++ b/nfs.md @@ -22,3 +22,6 @@ mkdir /remote_dir mount dns.ramwin.com:/remote_dir /remote_dir cat /remote_dir/test + + # 或者编辑 /etc/fstab + ip:/nfsexport /mnt/nfs nfs defaults 0 0 diff --git a/nginx.md b/nginx.md index 6bce684..38be891 100644 --- a/nginx.md +++ b/nginx.md @@ -54,6 +54,30 @@ make install * 每个worker又都是异步的, IO 多路复用 ## 配置 +### [多个服务代理](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method) +``` +http { + upstream backend { + server backend1.example.com; + server backend2.example.com; + server 192.0.0.1 backup; + } + + server { + location / { + proxy_pass http://backend; + } + } +} +``` +### server配置 +* 常用配置 +``` +server { + client_max_body_size 1G; // 最大上传尺寸 +} +``` + * 配置socket ``` location /ws { diff --git a/nginx/default b/nginx/default index 249118e..d902fbf 100644 --- a/nginx/default +++ b/nginx/default @@ -1,23 +1,3 @@ -## -# You should look at the following URL's in order to grasp a solid understanding -# of Nginx configuration files in order to fully unleash the power of Nginx. -# https://www.nginx.com/resources/wiki/start/ -# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/ -# https://wiki.debian.org/Nginx/DirectoryStructure -# -# In most cases, administrators will remove this file from sites-enabled/ and -# leave it as reference inside of sites-available where it will continue to be -# updated by the nginx packaging team. -# -# This file will automatically load configuration files provided by other -# applications, such as Drupal or Wordpress. These applications will be made -# available underneath a path with that package name, such as /drupal8. -# -# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples. -## - -# Default server configuration -# server { listen 80; listen [::]:80; diff --git a/nginx/docker/default b/nginx/docker/default new file mode 100644 index 0000000..1a0b976 --- /dev/null +++ b/nginx/docker/default @@ -0,0 +1,15 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + +} diff --git a/nginx/manjaro.conf b/nginx/manjaro.conf new file mode 100644 index 0000000..ad78d3b --- /dev/null +++ b/nginx/manjaro.conf @@ -0,0 +1,31 @@ +worker_processes 1; +include modules.d/*.conf; + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + sendfile on; + keepalive_timeout 65; + upstream backend { + server localhost:81; + server localhost:82; + server localhost:83; + } + server { + listen 80; + server_name localhost; + + location / { + proxy_pass http://backend; + } + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/nginx/wsl.ramwin.com b/nginx/wsl.ramwin.com new file mode 100644 index 0000000..81eef3b --- /dev/null +++ b/nginx/wsl.ramwin.com @@ -0,0 +1,8 @@ +server { + listen 80; + server_name wsl.ramwin.com; + location /proxy/ { + proxy_pass http://localhost:8000/proxy/; + add_header 'Access-Control-Allow-Origin' '*'; + } +} diff --git "a/nginx/\346\225\231\347\250\213.conf" "b/nginx/\346\225\231\347\250\213.conf" new file mode 100644 index 0000000..6911c0c --- /dev/null +++ "b/nginx/\346\225\231\347\250\213.conf" @@ -0,0 +1,120 @@ + +#user http; +worker_processes 1; + +#error_log logs/error.log; +#error_log logs/error.log notice; +#error_log logs/error.log info; + +#pid logs/nginx.pid; + + +# Load all installed modules +include modules.d/*.conf; + +events { + worker_connections 1024; +} + + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + server { + listen 80; + server_name localhost; + + #charset koi8-r; + + #access_log logs/host.access.log main; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} + } + + + # another virtual host using mix of IP-, name-, and port-based configuration + # + #server { + # listen 8000; + # listen somename:8080; + # server_name somename alias another.alias; + + # location / { + # root html; + # index index.html index.htm; + # } + #} + + + # HTTPS server + # + #server { + # listen 443 ssl; + # server_name localhost; + + # ssl_certificate cert.pem; + # ssl_certificate_key cert.key; + + # ssl_session_cache shared:SSL:1m; + # ssl_session_timeout 5m; + + # ssl_ciphers HIGH:!aNULL:!MD5; + # ssl_prefer_server_ciphers on; + + # location / { + # root html; + # index index.html index.htm; + # } + #} + +} diff --git a/postgresql.md b/postgresql.md index 1309896..4a616a8 100644 --- a/postgresql.md +++ b/postgresql.md @@ -149,6 +149,19 @@ where table_schema = 'public' order by 3 desc; ``` +* 查看各个索引的尺寸 +```sql +-- select pg_size_pretty(pg_relation_size('school_student_pkey')); +SELECT + tablename, indexname, + pg_size_pretty(pg_relation_size(indexname::regclass)) as index_size, + pg_size_pretty(pg_total_relation_size(tablename::regclass)) as total_total_size, + pg_size_pretty(pg_relation_size(tablename::regclass)) as table_data_size +FROM pg_indexes +ORDER by index_size +DESC limit 10; +``` + #### basic * 修改用户密码 ```sql diff --git a/postgresql/dump.sh b/postgresql/dump.sh new file mode 100644 index 0000000..ae93b4f --- /dev/null +++ b/postgresql/dump.sh @@ -0,0 +1,16 @@ +#!/bin/bash + + +export PGPASSFILE=/home/wangx/.pgpass +pg_dump schools \ + -f schools.sql + +pg_dump schools \ + --no-owner \ + -f schools_noonwer.sql + +pg_dump schools \ + --clean \ + --if-exists \ + --no-owner \ + -f schools_noonwer_if_exists.sql diff --git a/postgresql/pg_basebackup.help b/postgresql/pg_basebackup.help new file mode 100644 index 0000000..a0746ce --- /dev/null +++ b/postgresql/pg_basebackup.help @@ -0,0 +1,54 @@ +pg_basebackup takes a base backup of a running PostgreSQL server. + +Usage: + pg_basebackup [OPTION]... + +Options controlling the output: + -D, --pgdata=DIRECTORY receive base backup into directory + -F, --format=p|t output format (plain (default), tar) + -r, --max-rate=RATE maximum transfer rate to transfer data directory + (in kB/s, or use suffix "k" or "M") + -R, --write-recovery-conf + write configuration for replication + -T, --tablespace-mapping=OLDDIR=NEWDIR + relocate tablespace in OLDDIR to NEWDIR + --waldir=WALDIR location for the write-ahead log directory + -X, --wal-method=none|fetch|stream + include required WAL files with specified method + -z, --gzip compress tar output + -Z, --compress=0-9 compress tar output with given compression level + +General options: + -c, --checkpoint=fast|spread + set fast or spread checkpointing + -C, --create-slot create replication slot + -l, --label=LABEL set backup label + -n, --no-clean do not clean up after errors + -N, --no-sync do not wait for changes to be written safely to disk + -P, --progress show progress information + -S, --slot=SLOTNAME replication slot to use + -v, --verbose output verbose messages + -V, --version output version information, then exit + --manifest-checksums=SHA{224,256,384,512}|CRC32C|NONE + use algorithm for manifest checksums + --manifest-force-encode + hex encode all file names in manifest + --no-estimate-size do not estimate backup size in server side + --no-manifest suppress generation of backup manifest + --no-slot prevent creation of temporary replication slot + --no-verify-checksums + do not verify checksums + -?, --help show this help, then exit + +Connection options: + -d, --dbname=CONNSTR connection string + -h, --host=HOSTNAME database server host or socket directory + -p, --port=PORT database server port number + -s, --status-interval=INTERVAL + time between status packets sent to server (in seconds) + -U, --username=NAME connect as specified database user + -w, --no-password never prompt for password + -W, --password force password prompt (should happen automatically) + +Report bugs to . +PostgreSQL home page: diff --git a/redis/redis-cluster/README.md b/redis/redis-cluster/README.md index 1460d4e..5395bb2 100644 --- a/redis/redis-cluster/README.md +++ b/redis/redis-cluster/README.md @@ -1,4 +1,14 @@ -# 搭建文档 +# rediscluster +## 常用命令 +* [reshard and rebalance](https://severalnines.com/blog/hash-slot-resharding-and-rebalancing-redis-cluster/) +``` +redis-cli --cluster check localhost:7002 +redis-cli --cluster add-node localhost:7004 localhost:7000 +redis-cli --cluster rebalance localhost:7002 +redis-cli --cluster reshard localhost:7000 (把某个节点删除干净) +redis-cli --cluster del-node localhost:7000 abcd +``` +## 搭建文档 https://redis.io/docs/management/scaling/#create-and-use-a-redis-cluster 1. 进入每个cluster-test/700* 目录,执行 @@ -11,4 +21,10 @@ redis-server ./redis.conf redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 \ 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \ --cluster-replicas 1 + +注意需要各个节点之间可以访问 17000/1/2/3/4/5 端口 ``` + +## hash规则 +1. 使用crc16计算后对 2^14 取模 +2. 如果key里面有花括号{}, 只计算第一个花括号里面的数据 diff --git a/redis/redis-cluster/add_key.py b/redis/redis-cluster/add_key.py new file mode 100755 index 0000000..f6ee881 --- /dev/null +++ b/redis/redis-cluster/add_key.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import logging +import time +import redis +import string + + +logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s") + + +def main(): + logging.info("开始") + r = redis.RedisCluster(host="localhost", port=7003) + while True: + # prefix = str(time.time()) + + for i in string.ascii_letters: + r.set(i, i) + + for i in range(1000): + # r.set(prefix + str(i), i) + r.set(str(i), i) + time.sleep(0.0001) + logging.info("又一次写入了1026个key") + + +if __name__ == "__main__": + main() diff --git a/redis/redis-cluster/add_node.sh b/redis/redis-cluster/add_node.sh new file mode 100755 index 0000000..47c4124 --- /dev/null +++ b/redis/redis-cluster/add_node.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +set -ex +echo $1 +redis-cli --cluster add-node \ + $1 localhost:7000 \ + # 可以执行新节点是谁的child + # --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e +# redis-cli --cluster add-node localhost:7007 localhost:7000 --cluster-slave +# redis-cli --cluster add-node localhost:7008 localhost:7000 --cluster-slave diff --git a/redis/redis-cluster/balance.sh b/redis/redis-cluster/balance.sh new file mode 100755 index 0000000..dc11ea4 --- /dev/null +++ b/redis/redis-cluster/balance.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +redis-cli --cluster rebalance localhost:7005 diff --git a/redis/redis-cluster/check.sh b/redis/redis-cluster/check.sh new file mode 100755 index 0000000..6419828 --- /dev/null +++ b/redis/redis-cluster/check.sh @@ -0,0 +1,4 @@ +#!/bin/bash + + +redis-cli --cluster check localhost:700$1 diff --git a/redis/redis-cluster/clean.sh b/redis/redis-cluster/clean.sh new file mode 100755 index 0000000..3626e4c --- /dev/null +++ b/redis/redis-cluster/clean.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +find . -name 'nodes.conf' | xargs rm +find . -name 'dump.rdb' | xargs rm +find . -name 'appendonly.aof' | xargs rm diff --git a/redis/redis-cluster/cluster-test/7000/redis.conf b/redis/redis-cluster/cluster-test/7000/redis.conf index 31937a5..7be9a2e 100644 --- a/redis/redis-cluster/cluster-test/7000/redis.conf +++ b/redis/redis-cluster/cluster-test/7000/redis.conf @@ -1,5 +1,9 @@ port 7000 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7001/redis.conf b/redis/redis-cluster/cluster-test/7001/redis.conf index 689dc11..8546482 100644 --- a/redis/redis-cluster/cluster-test/7001/redis.conf +++ b/redis/redis-cluster/cluster-test/7001/redis.conf @@ -1,5 +1,9 @@ port 7001 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7002/redis.conf b/redis/redis-cluster/cluster-test/7002/redis.conf index ac61065..d60b608 100644 --- a/redis/redis-cluster/cluster-test/7002/redis.conf +++ b/redis/redis-cluster/cluster-test/7002/redis.conf @@ -1,5 +1,9 @@ port 7002 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7003/redis.conf b/redis/redis-cluster/cluster-test/7003/redis.conf index 5493390..be0c1dc 100644 --- a/redis/redis-cluster/cluster-test/7003/redis.conf +++ b/redis/redis-cluster/cluster-test/7003/redis.conf @@ -1,5 +1,9 @@ port 7003 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7004/redis.conf b/redis/redis-cluster/cluster-test/7004/redis.conf index 84959a3..04ea120 100644 --- a/redis/redis-cluster/cluster-test/7004/redis.conf +++ b/redis/redis-cluster/cluster-test/7004/redis.conf @@ -1,5 +1,9 @@ port 7004 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7005/redis.conf b/redis/redis-cluster/cluster-test/7005/redis.conf index b8dd323..a9274ce 100644 --- a/redis/redis-cluster/cluster-test/7005/redis.conf +++ b/redis/redis-cluster/cluster-test/7005/redis.conf @@ -1,5 +1,9 @@ port 7005 cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7006/redis.conf b/redis/redis-cluster/cluster-test/7006/redis.conf new file mode 100644 index 0000000..f8abe7f --- /dev/null +++ b/redis/redis-cluster/cluster-test/7006/redis.conf @@ -0,0 +1,9 @@ +port 7006 +cluster-enabled yes +cluster-config-file nodes.conf +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 +appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7007/redis.conf b/redis/redis-cluster/cluster-test/7007/redis.conf new file mode 100644 index 0000000..796738d --- /dev/null +++ b/redis/redis-cluster/cluster-test/7007/redis.conf @@ -0,0 +1,9 @@ +port 7007 +cluster-enabled yes +cluster-config-file nodes.conf +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 +appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7008/redis.conf b/redis/redis-cluster/cluster-test/7008/redis.conf new file mode 100644 index 0000000..f2f3031 --- /dev/null +++ b/redis/redis-cluster/cluster-test/7008/redis.conf @@ -0,0 +1,9 @@ +port 7008 +cluster-enabled yes +cluster-config-file nodes.conf +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 +appendonly yes +save 3600 1 300 100 60 10000 \ No newline at end of file diff --git a/redis/redis-cluster/cluster-test/7009/redis.conf b/redis/redis-cluster/cluster-test/7009/redis.conf new file mode 100644 index 0000000..f536fa4 --- /dev/null +++ b/redis/redis-cluster/cluster-test/7009/redis.conf @@ -0,0 +1,11 @@ +protected-mode no +port 7009 +cluster-enabled yes +cluster-config-file nodes.conf +# 2秒连不上就认为节点失败了 +cluster-node-timeout 2000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 +appendonly yes +save 3600 1 300 100 60 10000 +# cluster-announce-hostname db4 diff --git a/redis/redis-cluster/cluster-test/start.py b/redis/redis-cluster/cluster-test/start.py new file mode 100644 index 0000000..6762f58 --- /dev/null +++ b/redis/redis-cluster/cluster-test/start.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import subprocess +import os +from pathlib import Path + + +def main() -> None: + for i in range(7000, 7009): + os.chdir(Path(__file__).parent.joinpath(str(i))) + subprocess.Popen(["redis-server", "redis.conf"]) + + +if __name__ == "__main__": + main() diff --git a/redis/redis-cluster/create_cluster.sh b/redis/redis-cluster/create_cluster.sh new file mode 100755 index 0000000..9e414c7 --- /dev/null +++ b/redis/redis-cluster/create_cluster.sh @@ -0,0 +1,8 @@ +#!/bin/bash + + +redis-cli --cluster create \ + 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \ + 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \ + 127.0.0.1:7006 127.0.0.1:7007 127.0.0.1:7008 \ +--cluster-replicas 1 diff --git a/redis/redis-cluster/del_node.sh b/redis/redis-cluster/del_node.sh new file mode 100755 index 0000000..598689c --- /dev/null +++ b/redis/redis-cluster/del_node.sh @@ -0,0 +1,6 @@ +#!/bin/bash + + +set -ex +echo $1 +redis-cli --cluster del-node localhost:7000 $1 diff --git a/redis/redis-cluster/generate.py b/redis/redis-cluster/generate.py new file mode 100644 index 0000000..9949ec2 --- /dev/null +++ b/redis/redis-cluster/generate.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +from pathlib import Path + +import jinja2 + + +template = jinja2.Template(Path("redis.conf").read_text()) +for port in range(7000, 7009): + Path(f"cluster-test/{port}").mkdir(exist_ok=True) + with open(Path(f"cluster-test/{port}/redis.conf"), "w") as f: + f.write(template.render({ + "port": port, + "timeout": 2, + })) diff --git a/redis/redis-cluster/generate_supervisor.py b/redis/redis-cluster/generate_supervisor.py new file mode 100644 index 0000000..3aff83a --- /dev/null +++ b/redis/redis-cluster/generate_supervisor.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +from pathlib import Path +from jinja2 import Template + + +HOME = Path.home() + +DIRECTORY=f"{HOME}/github/linux-reference/redis/redis-cluster/cluster-test" + +template = Template( + "[program:redis_cluster_{{port}}]\n" + "command=redis-server redis.conf\n" + "directory={{DIRECTORY}}/{{port}}\n" + "stdout_logfile_maxbytes=4MB\n" + "stdout_logfile_backups=20\n" + "stderr_logfile_maxbytes=4MB\n" + "stderr_logfile_backups=20\n" + "autostart=true\n" + "autorestart=true\n" + "startretries=3\n" + "startsecs=20\n" + "redirect_stderr=false\n" + "user=wangx\n" + f'environment=PATH="/opt/homebrew/bin:{HOME}/venv/bin/:{HOME}/.local/bin:{HOME}/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"\n' + "stdout_logfile={{DIRECTORY}}/stdout.log\n" + "stderr_logfile={{DIRECTORY}}/stderr.log\n\n\n" +) + +with open(Path("supervisor_redis_cluster.ini"), "w") as f: + for port in range(7000, 7009): + f.write(template.render({"port": port, "DIRECTORY": DIRECTORY})) + diff --git a/redis/redis-cluster/get_key.py b/redis/redis-cluster/get_key.py new file mode 100644 index 0000000..39c99d8 --- /dev/null +++ b/redis/redis-cluster/get_key.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import redis +import string + +from redis.cluster import ClusterNode, RedisCluster + + +r = redis.RedisCluster(startup_nodes=[ + ClusterNode('localhost', 7001), + ClusterNode('localhost', 7002), + ], decode_responses=True) + +print("".join([ + r.get(i) or "无" + for i in string.ascii_letters +])) diff --git a/redis/redis-cluster/normal_add_key.py b/redis/redis-cluster/normal_add_key.py new file mode 100644 index 0000000..ab26cf6 --- /dev/null +++ b/redis/redis-cluster/normal_add_key.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import time +import redis +import string + + +prefix = str(time.time()) +r = redis.Redis(host="localhost", port=6379) + +for i in string.ascii_letters: + r.set(prefix + i, i) + +for i in range(10000): + r.set(prefix + str(i), i) diff --git a/redis/redis-cluster/redis.conf b/redis/redis-cluster/redis.conf index b64ebaf..45083cb 100644 --- a/redis/redis-cluster/redis.conf +++ b/redis/redis-cluster/redis.conf @@ -1,5 +1,9 @@ -port 700X +port {{port}} cluster-enabled yes cluster-config-file nodes.conf -cluster-node-timeout 5000 +# {{timeout}}秒连不上就认为节点失败了 +cluster-node-timeout {{timeout}}000 +# cluster内部通信端口, 默认是port + 10000 +# cluster-port 0 appendonly yes +save 3600 1 300 100 60 10000 diff --git a/redis/redis-cluster/redis.help b/redis/redis-cluster/redis.help new file mode 100644 index 0000000..87a45ee --- /dev/null +++ b/redis/redis-cluster/redis.help @@ -0,0 +1,123 @@ +redis-cli 7.2.5 + +Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]] + -h Server hostname (default: 127.0.0.1). + -p Server port (default: 6379). + -s Server socket (overrides hostname and port). + -a Password to use when connecting to the server. + You can also use the REDISCLI_AUTH environment + variable to pass this password more safely + (if both are used, this argument takes precedence). + --user Used to send ACL style 'AUTH username pass'. Needs -a. + --pass Alias of -a for consistency with the new --user option. + --askpass Force user to input password with mask from STDIN. + If this argument is used, '-a' and REDISCLI_AUTH + environment variable will be ignored. + -u Server URI. + -r Execute specified command N times. + -i When -r is used, waits seconds per command. + It is possible to specify sub-second times like -i 0.1. + This interval is also used in --scan and --stat per cycle. + and in --bigkeys, --memkeys, and --hotkeys per 100 cycles. + -n Database number. + -2 Start session in RESP2 protocol mode. + -3 Start session in RESP3 protocol mode. + -x Read last argument from STDIN (see example below). + -X Read argument from STDIN (see example below). + -d Delimiter between response bulks for raw formatting (default: \n). + -D Delimiter between responses for raw formatting (default: \n). + -c Enable cluster mode (follow -ASK and -MOVED redirections). + -e Return exit error code when command execution fails. + --tls Establish a secure TLS connection. + --sni Server name indication for TLS. + --cacert CA Certificate file to verify with. + --cacertdir Directory where trusted CA certificates are stored. + If neither cacert nor cacertdir are specified, the default + system-wide trusted root certs configuration will apply. + --insecure Allow insecure TLS connection by skipping cert validation. + --cert Client certificate to authenticate with. + --key Private key file to authenticate with. + --tls-ciphers Sets the list of preferred ciphers (TLSv1.2 and below) + in order of preference from highest to lowest separated by colon (":"). + See the ciphers(1ssl) manpage for more information about the syntax of this string. + --tls-ciphersuites Sets the list of preferred ciphersuites (TLSv1.3) + in order of preference from highest to lowest separated by colon (":"). + See the ciphers(1ssl) manpage for more information about the syntax of this string, + and specifically for TLSv1.3 ciphersuites. + --raw Use raw formatting for replies (default when STDOUT is + not a tty). + --no-raw Force formatted output even when STDOUT is not a tty. + --quoted-input Force input to be handled as quoted strings. + --csv Output in CSV format. + --json Output in JSON format (default RESP3, use -2 if you want to use with RESP2). + --quoted-json Same as --json, but produce ASCII-safe quoted strings, not Unicode. + --show-pushes Whether to print RESP3 PUSH messages. Enabled by default when + STDOUT is a tty but can be overridden with --show-pushes no. + --stat Print rolling stats about server: mem, clients, ... + --latency Enter a special mode continuously sampling latency. + If you use this mode in an interactive session it runs + forever displaying real-time stats. Otherwise if --raw or + --csv is specified, or if you redirect the output to a non + TTY, it samples the latency for 1 second (you can use + -i to change the interval), then produces a single output + and exits. + --latency-history Like --latency but tracking latency changes over time. + Default time interval is 15 sec. Change it using -i. + --latency-dist Shows latency as a spectrum, requires xterm 256 colors. + Default time interval is 1 sec. Change it using -i. + --lru-test Simulate a cache workload with an 80-20 distribution. + --replica Simulate a replica showing commands received from the master. + --rdb Transfer an RDB dump from remote server to local file. + Use filename of "-" to write to stdout. + --functions-rdb Like --rdb but only get the functions (not the keys) + when getting the RDB dump file. + --pipe Transfer raw Redis protocol from stdin to server. + --pipe-timeout In --pipe mode, abort with error if after sending all data. + no reply is received within seconds. + Default timeout: 30. Use 0 to wait forever. + --bigkeys Sample Redis keys looking for keys with many elements (complexity). + --memkeys Sample Redis keys looking for keys consuming a lot of memory. + --memkeys-samples Sample Redis keys looking for keys consuming a lot of memory. + And define number of key elements to sample + --hotkeys Sample Redis keys looking for hot keys. + only works when maxmemory-policy is *lfu. + --scan List all keys using the SCAN command. + --pattern Keys pattern when using the --scan, --bigkeys or --hotkeys + options (default: *). + --count Count option when using the --scan, --bigkeys or --hotkeys (default: 10). + --quoted-pattern Same as --pattern, but the specified string can be + quoted, in order to pass an otherwise non binary-safe string. + --intrinsic-latency Run a test to measure intrinsic system latency. + The test will run for the specified amount of seconds. + --eval Send an EVAL command using the Lua script at . + --ldb Used with --eval enable the Redis Lua debugger. + --ldb-sync-mode Like --ldb but uses the synchronous Lua debugger, in + this mode the server is blocked and script changes are + not rolled back from the server memory. + --cluster [args...] [opts...] + Cluster Manager command and arguments (see below). + --verbose Verbose mode. + --no-auth-warning Don't show warning message when using password on command + line interface. + --help Output this help and exit. + --version Output version and exit. + +Cluster Manager Commands: + Use --cluster help to list all available cluster manager commands. + +Examples: + cat /etc/passwd | redis-cli -x set mypasswd + redis-cli -D "" --raw dump key > key.dump && redis-cli -X dump_tag restore key2 0 dump_tag replace < key.dump + redis-cli -r 100 lpush mylist x + redis-cli -r 100 -i 1 info | grep used_memory_human: + redis-cli --quoted-input set '"null-\x00-separated"' value + redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3 + redis-cli --scan --pattern '*:12345*' + redis-cli --scan --pattern '*:12345*' --count 100 + + (Note: when using --eval the comma separates KEYS[] from ARGV[] items) + +When no command is given, redis-cli starts in interactive mode. +Type "help" in interactive mode for information on available commands +and settings. + diff --git a/redis/redis-cluster/reshard.sh b/redis/redis-cluster/reshard.sh new file mode 100755 index 0000000..e11f704 --- /dev/null +++ b/redis/redis-cluster/reshard.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +# reshard清理到0以后, 会自动变成slave +redis-cli + --cluster reshard localhost:7000 \ + --cluster-from \ + --cluster-to \ + --cluster-slots \ + --cluster-yes diff --git a/redis/redis-cluster/supervisor_redis_cluster.ini b/redis/redis-cluster/supervisor_redis_cluster.ini new file mode 100644 index 0000000..a201107 --- /dev/null +++ b/redis/redis-cluster/supervisor_redis_cluster.ini @@ -0,0 +1,18 @@ +[program:redis_cluster] +command=redis-server redis.conf +process_name=%(program_name)s_%(process_num)02d +directory=/home/wangx/github/linux-reference/redis/redis-cluster/cluster-test/70%(process_num)02d +numprocs=3 +stdout_logfile_maxbytes=4MB +stdout_logfile_backups=20 +stderr_logfile_maxbytes=4MB +stderr_logfile_backups=20 +autostart=true +autorestart=true +startretries=3 +startsecs=20 +redirect_stderr=false +user=wangx +environment=PATH="/home/wangx/venv/bin/:/home/wangx/.local/bin:/home/wangx/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" +stdout_logfile=/home/wangx/github/linux-reference/redis/redis-cluster/cluster-test/stdout.log +stderr_logfile=/home/wangx/github/linux-reference/redis/redis-cluster/cluster-test/stderr.log diff --git a/redis/redis-cluster/supervisor_redis_cluster_mac.ini b/redis/redis-cluster/supervisor_redis_cluster_mac.ini new file mode 100644 index 0000000..eb11e4d --- /dev/null +++ b/redis/redis-cluster/supervisor_redis_cluster_mac.ini @@ -0,0 +1,18 @@ +[program:redis_cluster] +process_name=redis_cluster_700%(process_num)s +numprocs=8 +command=redis-server redis.conf +directory=/Users/wangx/github/linux-reference/redis/redis-cluster/cluster-test/700%(process_num)s +stdout_logfile_maxbytes=4MB +stdout_logfile_backups=20 +stderr_logfile_maxbytes=4MB +stderr_logfile_backups=20 +autostart=true +autorestart=true +startretries=3 +startsecs=20 +redirect_stderr=false +user=wangx +environment=PATH="/opt/homebrew/bin:/Users/wangx/venv/bin/:/Users/wangx/.local/bin:/Users/wangx/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" +stdout_logfile=/Users/wangx/github/linux-reference/redis/redis-cluster/cluster-test/700%(process_num)s/stdout.log +stderr_logfile=/Users/wangx/github/linux-reference/redis/redis-cluster/cluster-test/700%(process_num)s/stderr.log diff --git "a/redis/redis-cluster/\346\265\213\350\257\225\344\270\200\347\233\264\346\216\250\351\200\201.py" "b/redis/redis-cluster/\346\265\213\350\257\225\344\270\200\347\233\264\346\216\250\351\200\201.py" new file mode 100644 index 0000000..555254c --- /dev/null +++ "b/redis/redis-cluster/\346\265\213\350\257\225\344\270\200\347\233\264\346\216\250\351\200\201.py" @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import time + +import redis + + +cluster = redis.RedisCluster(host='localhost', port=7002) + +def test(): + """ + 测试我一直用7002推送, 关闭7002时能否继续运行 + 会的,看来并且迁移slot的时候全程无感 + """ + cnt = 0 + while True: + cnt += 1 + cluster.rpush('list', time.time()) + time.sleep(0.1) + if cnt % 20 == 0: + print(cnt) + + +test() diff --git a/redis/redis.md b/redis/redis.md index a458b8b..a6dad45 100644 --- a/redis/redis.md +++ b/redis/redis.md @@ -1,4 +1,8 @@ # redis +```{toctree} +./sorted_set.md +``` + ## 集群搭建 ```{toctree} ./redis-cluster/README.md @@ -39,103 +43,12 @@ logfile "./log.log" src/redis-server ./redis.conf ``` -## Sorted Sets - -[官网][sorted set] - -sorted sets 保存的是字符串: float - -### zpopmin,zpopmax -返回score最大的若干个elements, 如果超过了,不会报错 -``` -> ZPOPMAX key [count] -[('three', 3.0), ('b', 2.0)] -[('c', 2.0)] -``` - -### 其他 -* BZPOPMIN(str|List[str], timeout) -如果timeout了,返回None, 否则返回(rediskey: str, value_key, score: float) - -* tutorial - -``` -> zadd hackers 1940 "Allan Kay" -(integer) 1 -> zadd hackers 1957 "Sophie Wilson" -(integer) 1 - -> zrange hackers 0 -1 -> zrevrange hackers 0 -1 -> zrange hackers 0 -1 withscores -> zrangebyscore hackers -inf 1950 -> zremrangebyscore hackers 1940 1960 -> zrange hackers "Anita Borg" # return the rank (from 0) or (nil) - -## Lexicographical scores # It should only be used in sets where all the members have the same score. 只能用于所有元素分数一致的情况,不然过滤会出现意想不到的结果 -> zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0 - "Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon" - 0 "Linus Torvalds" 0 "Alan Turing" -> zrange hackers 0 -1 -> zrangebylex hackers [B [P -``` - -* ZADD -[官网](https://redis.io/commands/zadd) +## Set ``` -ZADD key member # shell -redis.zadd(key, mapping) # python +REDIS.sadd('set', '1', '2') # 2 新加入的数量 +REDIS.sadd('set', '1') # 0 1已经加过了 ``` -* [ZCARD](https://redis.io/commands/zcard) -返回一个sorted sets的长度, 如果key不存在,就返回0 -* ZCOUNT -返回scrore在min和max之间的元素的数量 -默认是闭区间,如果想要得到开区间,就在对应的数字上加`(` -``` -ZCOUNT myset -inf +inf -ZCOUNT myset 1 3 -``` -* ZINCRBY key increment member -如果key不存在,就创建这个key, 如果member不存在,就加入member -increment可以是小数,整数,负数, 返回当前的value -* ZSCORE: `ZSCORE key member` -返回一个key里面member的score, 如果key不存在会返回nill(None) - -* [ZRANGE](https://redis.io/commands/zrange) -``` -zrange('mykey', -1, -1, withscores=True) # 找到最大的 -[('foo', 23.0)] -zrange('mykey', -1, -1) # 找到最大的 -['foo'] -``` - 1. > 从0开始, -1是最后一个, -2是倒数第二个 - 2. > 前后都是闭区间 - 3. > 不会报错,如果start大于stop,或者start大于长度,返回 [] -* [ZRANGEBYLEX](https://redis.io/commands/zrangebylex) -* [ ] ZRANK -* [ZREM](https://redis.io/commands/zrem): 删除一个元素 -基础代码 -``` -ZREM key member [member ...] -> 0 # 只要有一个member存在,就会返回1, 否则返回0 -``` -python用法 -``` -client.zrem(key, 'member', 'member2') -> 0 或者 1 # 只要一个member存在就返回1 -``` - -* [ ] ZREMRANGEBYLEX -* ZREMRANGEBYRANK -删除数据。注意是闭区间 -``` -redis.zremrangebyrank(key, 0, delete_cnt - 1) -``` -* ZREMRANGEBYSCORE -根据分数来删除 -* [ZREVRANGE](https://redis.io/commands/zrevrange): 类似ZRANGE但是是逆序的 - ## pipeline ```{note} 6.x版本使用pipeline的时候,key的过期状态不会变化,但是time时间会变化。 @@ -143,6 +56,7 @@ redis.zremrangebyrank(key, 0, delete_cnt - 1) ``` ## Progamming with Redis + ### [Redis as an LRU cache](https://redis.io/topics/lru-cache) * maxmemory 最大允许使用的内存 如果是用10M代表了10000000字节,如果是10MB代表了 10MiB * maxmemory-policy 占用内存过多时的操作 @@ -154,7 +68,8 @@ Starting with Redis 4.0, a new Least Frequently Used eviction mode is available. * lfu-log-factor 10: 需要次命中后,counter达到最大。我们系统里匹配一个人大概匹配几千次。所以匹配1000次后认为最大,暂时不删除, factor设置成0, decay-time要坚持数据保存一天,255次需要6分钟才允许删除一次。一共需要减少16次,所以设置成10吧 -## [Command 命令](https://redis.io/commands) +## Command +[docs](https://redis.io/commands) ### connections 链接文档 * [ ] auth @@ -197,6 +112,12 @@ client.hset("user1", mappting={"id": 1, "name": "ramwin"}) // return 0 表示 ``` ### Keys +* scan_iter 遍历所有的key +``` +for key in REDIS.scan_iter(): + print(key) +``` + * DEL ``` DEL key1 [key2 [key3]] @@ -543,6 +464,6 @@ if client.lock(task_key, timeout=10, blocking=False).acquire(): pass ``` -```{toctree} -./redis-cluster/README.md +## 性能 +```{include} ./测试redis的blpop的时延.md ``` diff --git a/redis/sorted_set.md b/redis/sorted_set.md new file mode 100644 index 0000000..958f3f9 --- /dev/null +++ b/redis/sorted_set.md @@ -0,0 +1,106 @@ +# Sorted Sets +## 常用示例 +* 获取任务 +``` +# 死循环快速处理任务 +while True: + info = redis.bzpopmin('key', timeout=30) + if info is None: + continue + _, taskid, score = info +``` + +[官网][sorted set] + +sorted sets 保存的是字符串: float + +## zpopmin,zpopmax +返回score最大的若干个elements, 如果超过了,不会报错 +``` +> ZPOPMAX key [count] +[('three', 3.0), ('b', 2.0)] +[('c', 2.0)] +``` + +## BZPOPMIN(str|List[str], timeout) +如果timeout了,返回None, 否则返回(rediskey: str, value_key, score: float) + +## Lexicographical scores +It should only be used in sets where all the members have the same score. 只能用于所有元素分数一致的情况,不然过滤会出现意想不到的结果 +> zadd hackers 0 "Alan Kay" 0 "Sophie Wilson" 0 "Richard Stallman" 0 + "Anita Borg" 0 "Yukihiro Matsumoto" 0 "Hedy Lamarr" 0 "Claude Shannon" + 0 "Linus Torvalds" 0 "Alan Turing" +> zrange hackers 0 -1 +> zrangebylex hackers [B [P + +## ZADD +[官网](https://redis.io/commands/zadd) +``` +ZADD key member # shell +redis.zadd(key, mapping) # python +``` + +## [ZCARD](https://redis.io/commands/zcard) +返回一个sorted sets的长度, 如果key不存在,就返回0 +* ZCOUNT +返回scrore在min和max之间的元素的数量 +默认是闭区间,如果想要得到开区间,就在对应的数字上加`(` +``` +ZCOUNT myset -inf +inf +ZCOUNT myset 1 3 +``` +## ZINCRBY key increment member +如果key不存在,就创建这个key, 如果member不存在,就加入member +increment可以是小数,整数,负数, 返回当前的value + +## ZSCORE: `ZSCORE key member` +返回一个key里面member的score, 如果key不存在会返回nill(None) + +## [ZRANGE](https://redis.io/commands/zrange) +``` +> zadd hackers 1940 "Allan Kay" +(integer) 1 +> zadd hackers 1957 "Sophie Wilson" +(integer) 1 + +> zrange hackers 0 -1 +> zrevrange hackers 0 -1 +> zrange hackers 0 -1 withscores +> zrangebyscore hackers -inf 1950 +> zremrangebyscore hackers 1940 1960 +> zrange hackers "Anita Borg" # return the rank (from 0) or (nil) +zrange('mykey', -1, -1, withscores=True) # 找到最大的 +[('foo', 23.0)] +zrange('mykey', -1, -1) # 找到最大的 +['foo'] +``` + +> 从0开始, -1是最后一个, -2是倒数第二个 +> 前后都是闭区间 +> 不会报错,如果start大于stop,或者start大于长度,返回 [] + +## [ZRANGEBYLEX](https://redis.io/commands/zrangebylex) +## [ ] ZRANK +## [ZREM](https://redis.io/commands/zrem): 删除一个元素 +基础代码 +``` +ZREM key member [member ...] +> 0 # 只要有一个member存在,就会返回1, 否则返回0 +``` +python用法 +``` +client.zrem(key, 'member', 'member2') +> 0 或者 1 # 只要一个member存在就返回1 +``` + +* [ ] ZREMRANGEBYLEX +* ZREMRANGEBYRANK +删除数据。注意是闭区间 +``` +redis.zremrangebyrank(key, 0, delete_cnt - 1) # 删除delete_cnt +redis.zremrangebyrank(key, -10086, -101) # 只保留最大的前100个数据 +``` +* ZREMRANGEBYSCORE +根据分数来删除 +* [ZREVRANGE](https://redis.io/commands/zrevrange): 类似ZRANGE但是是逆序的 + diff --git a/redis/test_sorted_set.py b/redis/test_sorted_set.py new file mode 100644 index 0000000..17134d7 --- /dev/null +++ b/redis/test_sorted_set.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# Xiang Wang + + +import logging +from redis import Redis + + +logging.basicConfig(level=logging.INFO) +REDIS = Redis(decode_responses=True) + + +def main(): + REDIS.delete("ss") + REDIS.zadd("ss", {"b": 3}) + badded, aadded, first = REDIS.pipeline()\ + .zadd("ss", {"b": -1})\ + .zadd("ss", {"a": 1})\ + .zrange("ss", 0, 0, withscores=True)\ + .execute() + logging.info("badded: %s, added: %s, first: %s", badded, aadded, first) + + +main() diff --git "a/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.md" "b/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.md" new file mode 100644 index 0000000..ee2d7f6 --- /dev/null +++ "b/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.md" @@ -0,0 +1,13 @@ +### 测试redis的blpop的时延 + +#### 方案 +一个进程, 不断地给list push进程的时间 +另外一个进程, 不断地pop. 并对比当前时间和pop出的时间. + +#### 脚本 +```{literalinclude} ./测试redis的blpop的时延.py +``` + +#### 结论 +* 本地使用redis的blpop, rpush需要144us +* 直接用list diff --git "a/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.py" "b/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.py" new file mode 100644 index 0000000..fbc4496 --- /dev/null +++ "b/redis/\346\265\213\350\257\225redis\347\232\204blpop\347\232\204\346\227\266\345\273\266.py" @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import click +import time + +from redis import Redis + + +REDIS = Redis(decode_responses=True) + + +def start_send(): + REDIS.delete("test_latency") + for i in range(10000): + time.sleep(0.0001) + REDIS.rpush("test_latency", int(time.time() * 1000000)) + print("发送完毕") + + +def start_receive(): + delay = 0 + for i in range(10000): + _, res = REDIS.blpop("test_latency", timeout=100) + current = int(time.time() * 1000000) + value = current - int(res) + delay += value + print("时延(us):", delay / 10000) + + +@click.command() +@click.option("--send", is_flag=True) +@click.option("--receive", is_flag=True) +def main(send: bool, receive: bool): + if send == receive: + raise ValueError + if send: + start_send() + else: + start_receive() + + +if __name__ == "__main__": + main() diff --git "a/redis/\346\265\213\350\257\225sorted_set\344\277\235\345\255\230\346\225\264\346\225\260\345\222\214\345\260\217\346\225\260\347\232\204\351\200\237\345\272\246.py" "b/redis/\346\265\213\350\257\225sorted_set\344\277\235\345\255\230\346\225\264\346\225\260\345\222\214\345\260\217\346\225\260\347\232\204\351\200\237\345\272\246.py" new file mode 100644 index 0000000..124a867 --- /dev/null +++ "b/redis/\346\265\213\350\257\225sorted_set\344\277\235\345\255\230\346\225\264\346\225\260\345\222\214\345\260\217\346\225\260\347\232\204\351\200\237\345\272\246.py" @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +import time + +from redis import Redis + + +REDIS = Redis(decode_responses=True) + + + +def test_int(): + start = time.time() + key = "sorted_set_int" + REDIS.delete(key) + + for i in range(10000): + REDIS.zadd(key, {str(i): int(time.time()) - 17_0000_0000}) + + for i in range(10000): + REDIS.zpopmax(key) + + end = time.time() + print("直接用int耗时: %f", end - start) + + +def test_float(): + start = time.time() + key = "sorted_set_float" + REDIS.delete(key) + + for i in range(10000): + REDIS.zadd(key, {str(i): time.time()}) + + for i in range(10000): + REDIS.zpopmax(key) + + end = time.time() + print("直接用float耗时: %f", end - start) + + +def main(): + test_int() + test_float() + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt index fabd9c5..1833d9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ +myst-parser sphinx sphinx-autobuild sphinx-design -myst-parser +sphinx-mermaid sphinx-rtd-theme sphinxcontrib-jquery -sphinx-mermaid +sphinxcontrib-mermaid diff --git a/restructed/be_include.md b/restructed/be_include.md new file mode 100644 index 0000000..c450e5c --- /dev/null +++ b/restructed/be_include.md @@ -0,0 +1 @@ +# 被include得大标题 diff --git a/restructed/be_include.py b/restructed/be_include.py new file mode 100644 index 0000000..7990324 --- /dev/null +++ b/restructed/be_include.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + + +def main(): + print("Hello World") diff --git a/restructed/include.rst b/restructed/include.rst index cc9f45a..d6e78b5 100644 --- a/restructed/include.rst +++ b/restructed/include.rst @@ -1,4 +1,4 @@ -被include的 -^^^^^^^^^^^ +被include的,文件restructured/include.rst +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 级别要一致 diff --git a/restructed/markdown.md b/restructed/markdown.md index 9951031..221731d 100644 --- a/restructed/markdown.md +++ b/restructed/markdown.md @@ -1,4 +1,40 @@ # markdown +```{contents} +``` + +```{toctree} +./mermaid.md +``` + +## include + +1. include代码 +使用 +``` +`` ` +{literalinclude} ./be_include.py +`` ` +``` +可以把代码展示出来 + +```{literalinclude} ./be_include.py +``` + +2. include markdown文件, 这样会导致层级比较大,注意被include的文件要比较小哦 +```{include} ./be_include.md +``` + +## 图片 +当前目录下可以直接用`![](./fish.png)` + +![](./fish.png){w=890px} +![](../test.png)[width=30] +![](../test.png){width=10} + +## 文字格式 +```{note} +我是笔记 +``` * 测试引用 我是引用 @@ -34,22 +70,12 @@ TODO ``` ## 图表 +```{toctree} +./mermaid.md +``` end是group里的end,不能随便用 -### [流程图](https://mermaid.js.org/syntax/flowchart.html) -通过`:::`可以设置类, `(){},<>,>/,可以设置框外观` -通过subgraph可以添加组 -```{mermaid} -flowchart TB; - Start --> check{校验是\n否橙色} - Start ~~~ 隐藏的线 - check --> |是| orange:::orange - check --> |否| red:::red - red & orange --> tooltip --> End - subgraph "tooltip" - a --> b - b --> c - end - classDef orange fill:#f96 - classDef red color: #f00 -``` + +## 列表待办列表 +- [ ] 未处理 +- [x] 已处理 diff --git a/restructed/markmap.html b/restructed/markmap.html new file mode 100644 index 0000000..c09c285 --- /dev/null +++ b/restructed/markmap.html @@ -0,0 +1,52 @@ + + + + + + +Markmap + + + + + + + + diff --git a/restructed/markmap.md b/restructed/markmap.md new file mode 100644 index 0000000..20f8d2c --- /dev/null +++ b/restructed/markmap.md @@ -0,0 +1,10 @@ +--- +markmap: + zoom: false +--- + +# markmap思维导图 + +## 标题一 + +## 标题二 diff --git a/restructed/mermaid.md b/restructed/mermaid.md new file mode 100644 index 0000000..688145c --- /dev/null +++ b/restructed/mermaid.md @@ -0,0 +1,116 @@ +# 测试mermaid + +## 顺序图 +```{mermaid} +sequenceDiagram + participant A as Alice
[复杂的名字] + A->>John: Hello John, how are you? + John-->>A: Great! + A-)John: See you later! +``` + +```{mermaid} +sequenceDiagram + participant Alice + participant Bob + Alice ->>+ John: Hello John, how are you? + John ->>- Alice: OK? + loop Healthcheck + John->John: Fight against hypochondria + end + Note right of John: Rational thoughts
prevail... + John -->>+Alice: Great! + John ->>+Bob: How about you? + activate John + John -->> Bob: How about you2? + activate John + Bob --> John: Jolly good! + deactivate John + deactivate John + Alice -->>-John: great! +``` + +## 流程图 +通过`:::`可以设置类, `(){},<>,>/,可以设置框外观` +通过subgraph可以添加组 +```{mermaid} +flowchart TB; +%%{init: {'flowchart' : {'curve' : "basis"}, 'theme': 'dark'}}%% + Start --> check{校验是\n否橙色} + Start --> 箭头 --> End + Start --- 连线 --- End + Start ==> 加粗箭头 ==> End + Start -- 纯文字 --- 加框 --- End + 箭头 ~~~ 隐藏线用来给箭头备注 ~~~ 箭头 + Start ~~~ 隐藏的线 + check --> |是| orange:::orange + check --> |否| red:::red + red & orange --> tooltip --> End + tooltip --> bigblock4:::big + subgraph "tooltip" + a --> b + b --> c + c --> d@{ shape: tag-rect, label: "Tagged process"} + end + classDef orange fill:#f96 + classDef big fontsize:100 + classDef red color: #f00 + classDef orange,big,red font-size:12pt; +``` + +## 甘特图 +```{mermaid} +%%{init: {'gantt': {'displayMode': 'compact'}}}%% +gantt + dateFormat YYYY-MM-DD + title Adding GANTT diagram functionality to mermaid + excludes weekends + %% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".) + + section A section + Completed task :done, des1, 2014-01-06,2014-01-08 + Active task :active, des2, 2014-01-09, 3d + Future task : des3, after des2, 5d + Future task2 : des4, after des3, 5d + + section Critical tasks + Completed task in the critical line :crit, done, 2014-01-06,24h + Implement parser and jison :crit, done, after des1, 2d + Create tests for parser :crit, active, 3d + Future task in critical line :crit, 5d + Create tests for renderer :2d + Add to mermaid :until isadded + Functionality added :milestone, isadded, 2014-01-25, 0d + + section Documentation + Describe gantt syntax :active, a1, after des1, 3d + Add gantt diagram to demo page :after a1 , 20h + Add another diagram to demo page :doc1, after a1 , 48h + + section Last section + Describe gantt syntax :after doc1, 3d + Add gantt diagram to demo page :20h + Add another diagram to demo page :48h + +``` + +## 思维导图 +```{mermaid} +mindmap + root((mindmap)) + Origins + Long history + ::icon(fa fa-book) + Popularisation + British popular psychology author Tony Buzan + Research + On effectiveness
and features + On Automatic creation + Uses + Creative techniques + Strategic planning + Argument mapping + Tools + Pen and paper + Mermaid +``` diff --git a/restructed/new_chapter.rst b/restructed/new_chapter.rst index e445b4f..8e6b9b5 100644 --- a/restructed/new_chapter.rst +++ b/restructed/new_chapter.rst @@ -1,2 +1,2 @@ 我是chapter但是被用在了下面 -=========================== +^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git "a/restructed/restructed\350\257\255\346\263\225.rst" "b/restructed/restructed\350\257\255\346\263\225.rst" index 5bc7f19..a7d2362 100644 --- "a/restructed/restructed\350\257\255\346\263\225.rst" +++ "b/restructed/restructed\350\257\255\346\263\225.rst" @@ -3,7 +3,10 @@ restructured .. toctree:: - ./markdown.md + ./toctree.rst + ./markdown.md + ./sub_menu.rst + ./sub_include.rst text style ---------- @@ -111,16 +114,4 @@ include会直接复制过来 .. include:: ./same_include.rst .. include:: ./include.rst - -toctree会当作上面的最后一个标题的子元素 - -.. toctree:: - - ./new_chapter.rst - -- 我想toctree但是当作大标题, 不行 - -.. toctree:: - :caption: 2 - - ./new_chapter2.rst +.. include:: ./sub_include.rst diff --git a/restructed/toctree.rst b/restructed/toctree.rst new file mode 100644 index 0000000..0b3a776 --- /dev/null +++ b/restructed/toctree.rst @@ -0,0 +1,18 @@ +toctree +------- + +tmp +~~~ + + +.. toctree:: + :caption: 我include了chapter和chapter2 + + ./new_chapter.rst + ./new_chapter2.rst + ./sub_menu.rst + + +**新的内容**toctree会当作上面的最后一个标题的子元素 + +- 我想toctree但是当作大标题, 不行 diff --git a/run_server.sh b/run_server.sh index ccf9add..b697ec5 100755 --- a/run_server.sh +++ b/run_server.sh @@ -15,4 +15,3 @@ sphinx-autobuild \ --re-ignore "\.git" \ --re-ignore "\.*\.swp" \ --re-ignore "\.*\.log" \ - diff --git a/script/apply_head_to_master.sh b/script/apply_head_to_master.sh new file mode 100644 index 0000000..7a3d482 --- /dev/null +++ b/script/apply_head_to_master.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +set -ex + +CURRENT=`git branch --show-current` +git checkout master +git cherry-pick $CURRENT +git checkout $CURRENT +git rebase master diff --git a/script/bundle.sh b/script/bundle.sh new file mode 100755 index 0000000..00ef74e --- /dev/null +++ b/script/bundle.sh @@ -0,0 +1,9 @@ +#!/bin/bash + + +set -ex +current_directory=`basename $(pwd)` +target=~/Desktop/$current_directory.bundle +current_branch=`git branch --show-current` +git bundle create $target origin/$current_branch...HEAD +git bundle verify $target diff --git a/script/excel-protocol.reg b/script/excel-protocol.reg new file mode 100755 index 0000000..a3677b1 --- /dev/null +++ b/script/excel-protocol.reg @@ -0,0 +1,12 @@ +Windows Registry Editor Version 5.00 + +[HKEY_CLASSES_ROOT\excel] +@="URL:Excel Protocol" +"URL Protocol"="" + +[HKEY_CLASSES_ROOT\excel\shell] + +[HKEY_CLASSES_ROOT\excel\shell\open] + +[HKEY_CLASSES_ROOT\excel\shell\open\command] +@="\"C:\\Users\\ramw\\AppData\\Local\\Programs\\Python\\Python313\\python.exe\" \"D:\\tmp\\open_excel.py\" \"%1\"" diff --git a/script/open_excel.py b/script/open_excel.py new file mode 100755 index 0000000..fa1be96 --- /dev/null +++ b/script/open_excel.py @@ -0,0 +1,54 @@ +""" +D:/tmp/open_excel.py +日志:D:/tmp/open_excel.log(只追加,不删除) +""" + +import sys, os, subprocess, traceback, re, urllib.parse as up +from datetime import datetime + +LOG_FILE = r'D:/tmp/open_excel.log' + +def log(msg): + ts = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + line = f'[{ts}] {msg}' + print(line) + with open(LOG_FILE, 'a', encoding='utf-8') as f: + f.write(line + '\n') + +try: + log('===== 新调用开始 =====') + log(f'sys.argv: {sys.argv}') + + raw = sys.argv[1] + log(f'原始 URL: {raw}') + + # 1. 统一去掉协议前缀(excel:// 或 excel:) + path = re.sub(r'^excel:?/*', '', raw, flags=re.IGNORECASE) + log(f'去掉协议后: {path}') + + # 2. URL 解码(%20、%5C 等) + path = up.unquote(path) + log(f'URL 解码后: {path}') + + # 3. 把 %5C → \ 并去掉开头多余的 \ + path = path.replace('\\', '/') # 先统一为正斜杠,避免双反斜杠 + path = path.lstrip('/') # 去掉开头的 / 或 \ + path = path.replace('/', '\\') # 再换回 Windows 反斜杠 + log(f'整理后路径: {path}') + + # 4. 拼成真正绝对路径 + path = os.path.abspath(path) + log(f'绝对路径: {path}') + + if not os.path.isfile(path): + log(f'❌ 文件不存在: {path}') + raise FileNotFoundError(path) + + excel = r"C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE" + log(f'Excel 路径: {excel}') + subprocess.Popen([excel, path]) + log('✅ Excel 已调起') + +except Exception: + log('=== 异常堆栈 ===') + log(traceback.format_exc()) diff --git a/script/rebase_to_master.sh b/script/rebase_to_master.sh index aaec475..b3b9120 100755 --- a/script/rebase_to_master.sh +++ b/script/rebase_to_master.sh @@ -22,7 +22,7 @@ set_masterbranch() set_masterbranch echo "当前主干分支"$masterbranch $HOME git checkout $masterbranch -git pull origin $masterbranch +# git pull origin $masterbranch for branch_name in $( git branch --format="%(refname:short)" | grep -v '$masterbranch' ); do git checkout $branch_name diff --git "a/script/\345\217\221\345\270\203\345\214\205.sh" "b/script/\345\217\221\345\270\203\345\214\205.sh" index 5dfbc9c..4afa584 100755 --- "a/script/\345\217\221\345\270\203\345\214\205.sh" +++ "b/script/\345\217\221\345\270\203\345\214\205.sh" @@ -2,8 +2,11 @@ # Xiang Wang(ramwin@qq.com) rm -rf dist/* -hatch build -hatch publish +# hatch build +# hatch publish +# +python3 -m build +twine upload dist/* # python3 setup.py sdist bdist_wheel # twine upload -r dist/* diff --git "a/script/\345\220\210\345\271\266\350\247\206\351\242\221\345\222\214\351\237\263\351\242\221.sh" "b/script/\345\220\210\345\271\266\350\247\206\351\242\221\345\222\214\351\237\263\351\242\221.sh" new file mode 100644 index 0000000..91c6775 --- /dev/null +++ "b/script/\345\220\210\345\271\266\350\247\206\351\242\221\345\222\214\351\237\263\351\242\221.sh" @@ -0,0 +1,5 @@ +#!/bin/bash +# Xiang Wang(ramwin@qq.com) + + +ffmpeg -i mp4.mp4 -i mp3.mp3 -map 0:v:0 -map 1:a:0 -acodec copy -shortest result.mp4 diff --git "a/script/\346\267\273\345\212\240submodule.sh" "b/script/\346\267\273\345\212\240submodule.sh" old mode 100644 new mode 100755 diff --git a/shellprogramming/README.md b/shellprogramming/README.md index 3b1d17e..f7ab3e3 100644 --- a/shellprogramming/README.md +++ b/shellprogramming/README.md @@ -100,7 +100,7 @@ array=($line) # 变成了列表 ``` ## [circle 循环](http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html) -* 用`\``可以执行命令 +* 用 \` 可以执行命令 ```shell for i in `ls test` do @@ -215,6 +215,17 @@ then fi ``` +### 判断当前机器 +``` +a=`hostname` +if [ $a = 'windowsamd' ] +then + echo '本地' +else + echo '不是本地' +fi +``` + ## exceptions ``` echo "error" diff --git a/shellprogramming/exit_with.sh b/shellprogramming/exit_with.sh new file mode 100644 index 0000000..52ffe39 --- /dev/null +++ b/shellprogramming/exit_with.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +# 或者 sh -c "exit 123" +echo "准备退出" $1 +exit $1 diff --git a/shellprogramming/for.sh b/shellprogramming/for.sh new file mode 100755 index 0000000..e7dfad3 --- /dev/null +++ b/shellprogramming/for.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Xiang Wang(ramwin@qq.com) + +HOST1="1" +HOST2="2" +HOST3="3" + +a=($HOST1 $HOST2 $HOST3) +for var in ${a[@]}; do + echo "循环" + echo $var +done diff --git "a/shellprogramming/if-\345\220\246\345\256\232.sh" "b/shellprogramming/if-\345\220\246\345\256\232.sh" new file mode 100644 index 0000000..020cd91 --- /dev/null +++ "b/shellprogramming/if-\345\220\246\345\256\232.sh" @@ -0,0 +1,5 @@ +exist=1 +if [ $exist -gt 0 ] +then + echo "存在文件" +fi diff --git a/shellprogramming/run.sh b/shellprogramming/run.sh new file mode 100644 index 0000000..2a54fdb --- /dev/null +++ b/shellprogramming/run.sh @@ -0,0 +1,8 @@ +set -e +echo "exit" +./exit_with.sh 0 && ./exit_with.sh 121 && ./exit_with.sh 12 +echo "之前的状态码是: " $? +echo "虽然之前的状态码不是0(2, 121, 128都会继续), 但是任务还是会继续执行" +echo "下面的ls会报错(2), 这个时候才会停止" +ls /ew +echo "exit" diff --git "a/shellprogramming/\345\217\202\346\225\260\345\212\240\346\263\250\351\207\212\347\232\204\346\226\271\346\263\225.sh" "b/shellprogramming/\345\217\202\346\225\260\345\212\240\346\263\250\351\207\212\347\232\204\346\226\271\346\263\225.sh" new file mode 100755 index 0000000..f4c85a1 --- /dev/null +++ "b/shellprogramming/\345\217\202\346\225\260\345\212\240\346\263\250\351\207\212\347\232\204\346\226\271\346\263\225.sh" @@ -0,0 +1,12 @@ +#!/bin/bash +# Xiang Wang(ramwin@qq.com) +# + + +# 方法: https://stackoverflow.com/questions/9522631/how-to-put-a-line-comment-for-a-multi-line-command + +echo_args=( + "123" + "3425" +) +echo "${echo_args[@]}" diff --git "a/shellprogramming/\346\212\245\351\224\231\344\270\215\346\211\247\350\241\214.sh" "b/shellprogramming/\346\212\245\351\224\231\344\270\215\346\211\247\350\241\214.sh" new file mode 100644 index 0000000..1376f06 --- /dev/null +++ "b/shellprogramming/\346\212\245\351\224\231\344\270\215\346\211\247\350\241\214.sh" @@ -0,0 +1,14 @@ +set -e +set -o pipefail + +echo "123"; +echo "456"; + +mkdir test && echo "OK" && mkdir test; # 多条命令 +mkdir test && mkdir test && mkdir test; # 多条命令不会触发exit + +echo "创建失败但是输出OK"; + +mkdir test2; + +echo "创建成功"; diff --git "a/shellprogramming/\350\216\267\345\217\226\345\217\202\346\225\260.sh" "b/shellprogramming/\350\216\267\345\217\226\345\217\202\346\225\260.sh" new file mode 100644 index 0000000..8db11e0 --- /dev/null +++ "b/shellprogramming/\350\216\267\345\217\226\345\217\202\346\225\260.sh" @@ -0,0 +1,12 @@ +#!/bin/bash +# Xiang Wang(ramwin@qq.com) + + +param=$1 + +if [ ! $param ] +then + read -p "输入参数: " param +fi + +echo "参数" $param diff --git "a/shellprogramming/\350\216\267\345\217\226\351\224\231\350\257\257\347\240\201.sh" "b/shellprogramming/\350\216\267\345\217\226\351\224\231\350\257\257\347\240\201.sh" new file mode 100644 index 0000000..1a50457 --- /dev/null +++ "b/shellprogramming/\350\216\267\345\217\226\351\224\231\350\257\257\347\240\201.sh" @@ -0,0 +1,16 @@ +set -e +echo "开始" +./exit_with.sh 0 +a=$? +# a=3; +echo -n "a=" +echo $a; +echo "正常OK"; + +echo "异常就无返回" +./exit_with.sh 1 +a=$? +# a=3; +echo "a=" +echo $a; +echo "结束" diff --git a/software.md b/software.md index b5830fb..0fde157 100644 --- a/software.md +++ b/software.md @@ -1,6 +1,10 @@ # SOFTWARE软件 ## 运维工具 +```{toctree} +./使用mdadm创建raid.md +``` + ### nmon 查看各个磁盘的读写速度 @@ -12,6 +16,14 @@ shr: 共享内存(动态链接库会只保留一份) ``` htop -u wangx # 仅看某个用户的进程 ``` + +* 排除掉某个进程的性能 + +```bash +htop -p "$(pgrep -vfd, 'agava')" +htop -p "$(pgrep -vfd, 'java|python')" +``` + ### iftop: ``` iftop -i ens3 -P 查看某个网卡的网络进出情况 @@ -19,6 +31,12 @@ iftop -i ens3 -P 查看某个网卡的网络进出情况 ### ip: 查看网卡端口 `ip link show` +### ncdu 查看磁盘占用 +* 查看磁盘占用 +``` +sudo ncdu -x / # -x用来只看当前的磁盘 +``` + ### hddtemp: 查看硬盘的温度 ## 字符处理 @@ -27,13 +45,6 @@ iftop -i ens3 -P 查看某个网卡的网络进出情况 awk '{print $1}' filename ``` - -## Mac -```{toctree} -./mac/shortcut.md -./mac/software软件安装卸载brew.md -``` - ## 服务类 ```{toctree} :maxdepth: 2 @@ -198,6 +209,14 @@ apt install language-pack-zh-hans LANG="zh_CN.UTF-8" ``` +## lz4 +* 支持解压合并操作 +``` +tar cvf - directory | lz4 - target.tar.lz4 +lz4 -dc target_1.tar.lz4 | tar -xv # 支持多次压缩 +lz4 -dc target_1.tar.lz4 | tar -xv +``` + ## nnn 文件管理 ``` diff --git a/software/lz4/abc/directory/a.md b/software/lz4/abc/directory/a.md new file mode 100644 index 0000000..f76ee31 --- /dev/null +++ b/software/lz4/abc/directory/a.md @@ -0,0 +1 @@ +i'm in a file diff --git a/software/lz4/abc/directory/b.md b/software/lz4/abc/directory/b.md new file mode 100644 index 0000000..f47dea2 --- /dev/null +++ b/software/lz4/abc/directory/b.md @@ -0,0 +1 @@ +i'm in b file diff --git a/software/terminal/terminal_link.json b/software/terminal/terminal_link.json new file mode 120000 index 0000000..8f6765b --- /dev/null +++ b/software/terminal/terminal_link.json @@ -0,0 +1 @@ +/mnt/c/Users/ramw//AppData/Local/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json \ No newline at end of file diff --git "a/software/terminal/terminal\351\205\215\347\275\256.json" "b/software/terminal/terminal\351\205\215\347\275\256.json" new file mode 100755 index 0000000..9a6be6b --- /dev/null +++ "b/software/terminal/terminal\351\205\215\347\275\256.json" @@ -0,0 +1,332 @@ +{ + "路径": "C:\Users\w00827035\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json", + "$help": "https://aka.ms/terminal-documentation", + "$schema": "https://aka.ms/terminal-profiles-schema", + "actions": + [ + { + "command": + { + "action": "copy", + "singleLine": false + }, + "keys": "ctrl+c" + }, + { + "command": "paste" + }, + { + "command": "find", + "keys": "ctrl+shift+f" + }, + { + "command": + { + "action": "splitPane", + "split": "auto", + "splitMode": "duplicate" + }, + "keys": "alt+shift+d" + }, + { + "command": "unbound", + "keys": "ctrl+v" + } + ], + "copyFormatting": "none", + "copyOnSelect": false, + "defaultProfile": "{367cae4b-7b06-5a7c-8815-c7dec2fdb626}", + "newTabMenu": + [ + { + "type": "remainingProfiles" + } + ], + "profiles": + { + "defaults": {}, + "list": + [ + { + "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", + "hidden": false, + "name": "Windows PowerShell" + }, + { + "commandline": "%SystemRoot%\\System32\\cmd.exe", + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "hidden": false, + "name": "\u547d\u4ee4\u63d0\u793a\u7b26" + }, + { + "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}", + "hidden": false, + "name": "Azure Cloud Shell", + "source": "Windows.Terminal.Azure" + }, + { + "font": + { + "size": 18.0 + }, + "guid": "{2ece5bfe-50ed-5f3a-ab87-5cd4baafed2b}", + "hidden": false, + "name": "Git Bash", + "source": "Git" + }, + { + "guid": "{963ff2f7-6aed-5ce3-9d91-90d99571f53a}", + "hidden": true, + "name": "Ubuntu-24.04", + "source": "Windows.Terminal.Wsl" + }, + { + "bellStyle": "none", + "colorScheme": "Ubuntu", + "font": + { + "size": 24.0 + }, + "guid": "{367cae4b-7b06-5a7c-8815-c7dec2fdb626}", + "hidden": false, + "name": "Ubuntu-24.04", + "source": "Microsoft.WSL" + } + ] + }, + "schemes": + [ + { + "background": "#0C0C0C", + "black": "#0C0C0C", + "blue": "#0037DA", + "brightBlack": "#767676", + "brightBlue": "#3B78FF", + "brightCyan": "#61D6D6", + "brightGreen": "#16C60C", + "brightPurple": "#B4009E", + "brightRed": "#E74856", + "brightWhite": "#F2F2F2", + "brightYellow": "#F9F1A5", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#CCCCCC", + "green": "#13A10E", + "name": "Campbell", + "purple": "#881798", + "red": "#C50F1F", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#C19C00" + }, + { + "background": "#012456", + "black": "#0C0C0C", + "blue": "#0037DA", + "brightBlack": "#767676", + "brightBlue": "#3B78FF", + "brightCyan": "#61D6D6", + "brightGreen": "#16C60C", + "brightPurple": "#B4009E", + "brightRed": "#E74856", + "brightWhite": "#F2F2F2", + "brightYellow": "#F9F1A5", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#CCCCCC", + "green": "#13A10E", + "name": "Campbell Powershell", + "purple": "#881798", + "red": "#C50F1F", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#C19C00" + }, + { + "background": "#282C34", + "black": "#282C34", + "blue": "#61AFEF", + "brightBlack": "#5A6374", + "brightBlue": "#61AFEF", + "brightCyan": "#56B6C2", + "brightGreen": "#98C379", + "brightPurple": "#C678DD", + "brightRed": "#E06C75", + "brightWhite": "#DCDFE4", + "brightYellow": "#E5C07B", + "cursorColor": "#FFFFFF", + "cyan": "#56B6C2", + "foreground": "#DCDFE4", + "green": "#98C379", + "name": "One Half Dark", + "purple": "#C678DD", + "red": "#E06C75", + "selectionBackground": "#FFFFFF", + "white": "#DCDFE4", + "yellow": "#E5C07B" + }, + { + "background": "#FAFAFA", + "black": "#383A42", + "blue": "#0184BC", + "brightBlack": "#4F525D", + "brightBlue": "#61AFEF", + "brightCyan": "#56B5C1", + "brightGreen": "#98C379", + "brightPurple": "#C577DD", + "brightRed": "#DF6C75", + "brightWhite": "#FFFFFF", + "brightYellow": "#E4C07A", + "cursorColor": "#4F525D", + "cyan": "#0997B3", + "foreground": "#383A42", + "green": "#50A14F", + "name": "One Half Light", + "purple": "#A626A4", + "red": "#E45649", + "selectionBackground": "#4F525D", + "white": "#FAFAFA", + "yellow": "#C18301" + }, + { + "background": "#002B36", + "black": "#002B36", + "blue": "#268BD2", + "brightBlack": "#073642", + "brightBlue": "#839496", + "brightCyan": "#93A1A1", + "brightGreen": "#586E75", + "brightPurple": "#6C71C4", + "brightRed": "#CB4B16", + "brightWhite": "#FDF6E3", + "brightYellow": "#657B83", + "cursorColor": "#FFFFFF", + "cyan": "#2AA198", + "foreground": "#839496", + "green": "#859900", + "name": "Solarized Dark", + "purple": "#D33682", + "red": "#DC322F", + "selectionBackground": "#FFFFFF", + "white": "#EEE8D5", + "yellow": "#B58900" + }, + { + "background": "#FDF6E3", + "black": "#002B36", + "blue": "#268BD2", + "brightBlack": "#073642", + "brightBlue": "#839496", + "brightCyan": "#93A1A1", + "brightGreen": "#586E75", + "brightPurple": "#6C71C4", + "brightRed": "#CB4B16", + "brightWhite": "#FDF6E3", + "brightYellow": "#657B83", + "cursorColor": "#002B36", + "cyan": "#2AA198", + "foreground": "#657B83", + "green": "#859900", + "name": "Solarized Light", + "purple": "#D33682", + "red": "#DC322F", + "selectionBackground": "#073642", + "white": "#EEE8D5", + "yellow": "#B58900" + }, + { + "background": "#000000", + "black": "#000000", + "blue": "#3465A4", + "brightBlack": "#555753", + "brightBlue": "#729FCF", + "brightCyan": "#34E2E2", + "brightGreen": "#8AE234", + "brightPurple": "#AD7FA8", + "brightRed": "#EF2929", + "brightWhite": "#EEEEEC", + "brightYellow": "#FCE94F", + "cursorColor": "#FFFFFF", + "cyan": "#06989A", + "foreground": "#D3D7CF", + "green": "#4E9A06", + "name": "Tango Dark", + "purple": "#75507B", + "red": "#CC0000", + "selectionBackground": "#FFFFFF", + "white": "#D3D7CF", + "yellow": "#C4A000" + }, + { + "background": "#FFFFFF", + "black": "#000000", + "blue": "#3465A4", + "brightBlack": "#555753", + "brightBlue": "#729FCF", + "brightCyan": "#34E2E2", + "brightGreen": "#8AE234", + "brightPurple": "#AD7FA8", + "brightRed": "#EF2929", + "brightWhite": "#EEEEEC", + "brightYellow": "#FCE94F", + "cursorColor": "#000000", + "cyan": "#06989A", + "foreground": "#555753", + "green": "#4E9A06", + "name": "Tango Light", + "purple": "#75507B", + "red": "#CC0000", + "selectionBackground": "#555753", + "white": "#D3D7CF", + "yellow": "#C4A000" + }, + { + "background": "#300A24", + "black": "#171421", + "blue": "#0037DA", + "brightBlack": "#767676", + "brightBlue": "#08458F", + "brightCyan": "#2C9FB3", + "brightGreen": "#26A269", + "brightPurple": "#A347BA", + "brightRed": "#C01C28", + "brightWhite": "#F2F2F2", + "brightYellow": "#A2734C", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#FFFFFF", + "green": "#26A269", + "name": "Ubuntu", + "purple": "#881798", + "red": "#C21A23", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#A2734C" + }, + { + "background": "#000000", + "black": "#000000", + "blue": "#000080", + "brightBlack": "#808080", + "brightBlue": "#0000FF", + "brightCyan": "#00FFFF", + "brightGreen": "#00FF00", + "brightPurple": "#FF00FF", + "brightRed": "#FF0000", + "brightWhite": "#FFFFFF", + "brightYellow": "#FFFF00", + "cursorColor": "#FFFFFF", + "cyan": "#008080", + "foreground": "#C0C0C0", + "green": "#008000", + "name": "Vintage", + "purple": "#800080", + "red": "#800000", + "selectionBackground": "#FFFFFF", + "white": "#C0C0C0", + "yellow": "#808000" + } + ], + "themes": [] +} diff --git a/software/terminal/windows_5800.json b/software/terminal/windows_5800.json new file mode 100755 index 0000000..57d5bed --- /dev/null +++ b/software/terminal/windows_5800.json @@ -0,0 +1,199 @@ +{ + "$help": "https://aka.ms/terminal-documentation", + "$schema": "https://aka.ms/terminal-profiles-schema-preview", + "actions": + [ + { + "command": + { + "action": "copy", + "singleLine": false + }, + "id": "User.copy.644BA8F2" + }, + { + "command": "paste", + "id": "User.paste" + }, + { + "command": "find", + "id": "User.find" + }, + { + "command": + { + "action": "splitPane", + "split": "auto", + "splitMode": "duplicate" + }, + "id": "User.splitPane.A6751878" + } + ], + "copyFormatting": "none", + "copyOnSelect": false, + "defaultProfile": "{51855cb2-8cce-5362-8f54-464b92b32386}", + "keybindings": + [ + { + "id": "User.find", + "keys": "ctrl+shift+f" + }, + { + "id": null, + "keys": "ctrl+v" + }, + { + "id": "User.copy.644BA8F2", + "keys": "ctrl+c" + }, + { + "id": "User.splitPane.A6751878", + "keys": "alt+shift+d" + } + ], + "newTabMenu": + [ + { + "type": "remainingProfiles" + } + ], + "profiles": + { + "defaults": + { + "colorScheme": "Campbell (modified)" + }, + "list": + [ + { + "commandline": "%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", + "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}", + "hidden": false, + "name": "Windows PowerShell" + }, + { + "commandline": "%SystemRoot%\\System32\\cmd.exe", + "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}", + "hidden": false, + "name": "\u547d\u4ee4\u63d0\u793a\u7b26" + }, + { + "bellStyle": "none", + "closeOnExit": "always", + "colorScheme": "ramwin", + "guid": "{2c4de342-38b7-51cf-b940-2309a097f518}", + "hidden": true, + "name": "Ubuntu", + "source": "Windows.Terminal.Wsl" + }, + { + "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}", + "hidden": false, + "name": "Azure Cloud Shell", + "source": "Windows.Terminal.Azure" + }, + { + "bellStyle": "taskbar", + "closeOnExit": "always", + "colorScheme": "ramwin", + "font": + { + "size": 18 + }, + "guid": "{51855cb2-8cce-5362-8f54-464b92b32386}", + "hidden": false, + "icon": null, + "name": "Ubuntu", + "source": "CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc" + }, + { + "closeOnExit": "always", + "colorScheme": "Ubuntu-22.04-ColorScheme", + "guid": "{17bf3de4-5353-5709-bcf9-835bd952a95e}", + "hidden": true, + "name": "Ubuntu-22.04", + "source": "Windows.Terminal.Wsl" + }, + { + "guid": "{4ff56d04-d9cf-57ea-bae2-ad396374e7e3}", + "hidden": false, + "icon": null, + "name": "Ubuntu 22.04.5 LTS", + "source": "CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc" + } + ] + }, + "schemes": + [ + { + "background": "#0C0C0C", + "black": "#0C0C0C", + "blue": "#8AA9DA", + "brightBlack": "#767676", + "brightBlue": "#95A5FF", + "brightCyan": "#61D6D6", + "brightGreen": "#16C60C", + "brightPurple": "#B4009E", + "brightRed": "#E74856", + "brightWhite": "#F2F2F2", + "brightYellow": "#F9F1A5", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#CCCCCC", + "green": "#13A10E", + "name": "Campbell (modified)", + "purple": "#881798", + "red": "#C50F1F", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#C19C00" + }, + { + "background": "#300A24", + "black": "#171421", + "blue": "#0037DA", + "brightBlack": "#767676", + "brightBlue": "#08458F", + "brightCyan": "#2C9FB3", + "brightGreen": "#26A269", + "brightPurple": "#A347BA", + "brightRed": "#C01C28", + "brightWhite": "#F2F2F2", + "brightYellow": "#A2734C", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#FFFFFF", + "green": "#26A269", + "name": "Ubuntu", + "purple": "#881798", + "red": "#C21A23", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#A2734C" + }, + { + "background": "#000000", + "black": "#0C0C0C", + "blue": "#9DC7DA", + "brightBlack": "#767676", + "brightBlue": "#3B78FF", + "brightCyan": "#61D6D6", + "brightGreen": "#16C60C", + "brightPurple": "#B4009E", + "brightRed": "#E74856", + "brightWhite": "#F2F2F2", + "brightYellow": "#F9F1A5", + "cursorColor": "#FFFFFF", + "cyan": "#3A96DD", + "foreground": "#FFFFFF", + "green": "#13A10E", + "name": "ramwin", + "purple": "#881798", + "red": "#C50F1F", + "selectionBackground": "#FFFFFF", + "white": "#CCCCCC", + "yellow": "#C19C00" + } + ], + "themes": [] +} \ No newline at end of file diff --git a/software/terminal/windows_5800_link.json b/software/terminal/windows_5800_link.json new file mode 120000 index 0000000..0e16134 --- /dev/null +++ b/software/terminal/windows_5800_link.json @@ -0,0 +1 @@ +/mnt/c/Users/ramwi/AppData/Local/Packages/Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe/LocalState/settings.json \ No newline at end of file diff --git a/software/vscode/settings.json b/software/vscode/settings.json index 1033666..4a663ae 100644 --- a/software/vscode/settings.json +++ b/software/vscode/settings.json @@ -1,10 +1,23 @@ { - "security.workspace.trust.untrustedFiles": "open", - "editor.fontSize": 12, + "_comment": "/home/wangx/.config/Code - OSS/User/settings.json", + "原始文件": "~/.config/Code - OSS/User/settings.json", + "[vue]": { + "editor.defaultFormatter": "Vue.volar" + }, "debug.console.fontSize": 24, - "window.zoomLevel": 3, "editor.detectIndentation": false, - "python.defaultInterpreterPath": "/home/wangx/venv/bin/python", + "editor.fontSize": 12, + "editor.renderFinalNewline": "off", + "explorer.confirmDelete": false, + "explorer.confirmDragAndDrop": false, + "files.autoSave": "onFocusChange", "files.insertFinalNewline": true, - "explorer.confirmDelete": false + "files.eol": "\n", + "git.autofetch": true, + "git.openRepositoryInParentFolders": "always", + "python.defaultInterpreterPath": "/home/wangx/venv/bin/python", + "security.workspace.trust.untrustedFiles": "open", + "typescript.updateImportsOnFileMove.enabled": "always", + "window.zoomLevel": 1, + "workbench.colorTheme": "Default Light Modern" } diff --git a/sqlite/README.md b/sqlite/README.md index 64dab8c..b266221 100644 --- a/sqlite/README.md +++ b/sqlite/README.md @@ -1,3 +1,4 @@ +# sqlite [sqlite tutorial 官网](http://www.sqlitetutorial.net/) [sqlite org](https://sqlite.org/index.html) @@ -144,3 +145,9 @@ sqlite3 test.db .read .import 文件名 表名 ``` + +## 命令设置 +* .show # 查看基础设置 +* .header on +* .mode column +* .timer on diff --git a/supervisor.ini b/supervisor.ini index 9a7f23e..233310c 100644 --- a/supervisor.ini +++ b/supervisor.ini @@ -1,5 +1,15 @@ [program:linux-reference] -command=sh run_server.sh +command=sphinx-autobuild + --color + --host 0.0.0.0 + -j auto + --port 18002 + . _build/html/ + --re-ignore "\.mypy_cache" + --re-ignore "\.git" + --re-ignore "\.*\.swp" + --re-ignore "\.*\.log" + directory=/home/wangx/github/linux-reference stdout_logfile_maxbytes=4MB stdout_logfile_backups=20 @@ -7,10 +17,10 @@ stderr_logfile_maxbytes=4MB stderr_logfile_backups=20 autostart=true autorestart=true -startretries=3 +startretries=0 startsecs=20 redirect_stderr=false user=wangx -environment=PATH="/home/wangx/venv/bin/:/home/wangx/.local/bin:/home/wangx/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin" -stdout_logfile=/home/wangx/github/linux-reference/stdout.log -stderr_logfile=/home/wangx/github/linux-reference/stderr.log +environment=HOME="/home/wangx",USER="wangx",PATH="/home/wangx/venv/bin/:/home/wangx/.local/bin:/home/wangx/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin",RAMWIN="LINUX_REFERENCE" +stdout_logfile=/home/wangx/github/linux-reference/stdout_%(process_num)d.log +stderr_logfile=/home/wangx/github/linux-reference/stderr_%(process_num)d.log diff --git a/supervisor_mac.ini b/supervisor_mac.ini new file mode 100644 index 0000000..6c12c9c --- /dev/null +++ b/supervisor_mac.ini @@ -0,0 +1,26 @@ +[program:linux-reference] +command=sphinx-autobuild + --color + --host 0.0.0.0 + -j auto + --port 18002 + . _build/html/ + --re-ignore "\.mypy_cache" + --re-ignore "\.git" + --re-ignore "\.*\.swp" + --re-ignore "\.*\.log" + +directory=/Users/wangx/github/linux-reference +stdout_logfile_maxbytes=4MB +stdout_logfile_backups=20 +stderr_logfile_maxbytes=4MB +stderr_logfile_backups=20 +autostart=true +autorestart=true +startretries=0 +startsecs=20 +redirect_stderr=false +user=wangx +environment=HOME="/Users/wangx",USER="wangx",PATH="/Users/wangx/venv/bin/:/Users/wangx/.local/bin:/Users/wangx/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin",RAMWIN="LINUX_REFERENCE" +stdout_logfile=/Users/wangx/github/linux-reference/stdout_%(process_num)d.log +stderr_logfile=/Users/wangx/github/linux-reference/stderr_%(process_num)d.log diff --git a/vim.md b/vim.md index 60c22ba..2806191 100644 --- a/vim.md +++ b/vim.md @@ -1,4 +1,13 @@ # vim +## 安装 +``` +git clone https://github.com/vim/vim.git github/other/vim +cd github/other/vim +./configure --with-features=huge --enable-python3interp +make -j # use multi process +sudo make install +``` + ## 导航 * [配置](http://edyfox.codecarver.org/html/_vimrc_for_beginners.html) ``` diff --git a/vscode.json b/vscode.json deleted file mode 100644 index 0b10cb3..0000000 --- a/vscode.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "workbench.colorTheme": "Solarized Light", - "editor.codeActionsOnSave": { - "source.fixAll": true - } -} diff --git a/vscode/settings.json b/vscode/settings.json deleted file mode 100644 index 346ae7f..0000000 --- a/vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "editor.renderFinalNewline": "off", - "files.eol": "\n", - "files.insertFinalNewline": true, - "files.autoSave": "onFocusChange", - "原始文件": "~/.config/Code - OSS/User/settings.json" -} diff --git a/zshrc b/zshrc new file mode 100644 index 0000000..a0f0da5 --- /dev/null +++ b/zshrc @@ -0,0 +1,45 @@ +# mac才需要 +# eval "$(/opt/homebrew/bin/brew shellenv)" + +# ZSH_THEME=3den.zsh +# . ~/github/other/ohmyzsh/themes/3den.zsh-theme +# ZSH_THEME=powerlevel9k +export LANG=zh_CN.UTF-8 +# . $HOME/.bash_aliases +autoload -U colors && colors +export PS1="%{$fg[red]%}%n%{$reset_color%}@%{$fg[blue]%}%m %{$fg[yellow]%}%~ %{$reset_color%}%% " +PATH=\ +/opt/homebrew/bin/\ +:$HOME/Library/Python/3.9/bin/\ +:$PATH +export HOST="Mac" +source $HOME/github/linux-reference/baserc + +COLOR_DEF=$'%f' +COLOR_USR=$'%F{243}' # 灰色 +COLOR_DIR=$'%F{197}' # 璀璨洋红 +# COLOR_GIT=$'%F{39}' # 亮蓝色 +COLOR_GIT=$'%F{002}' # 绿色 +setopt PROMPT_SUBST +bindkey -e # 下面2行的汇总 +bindkey '^E' end-of-line +bindkey '^A' beginning-of-line +bindkey "^[[1;5C" forward-word +bindkey "^[[1;5D" backward-word + +export PROMPT='${COLOR_USR}%n ${COLOR_DIR}%~ ${COLOR_GIT}$(show_branch.py)${COLOR_DEF} $ ' + +# export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git" +# export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git" +# export HOMEBREW_INSTALL_FROM_API=1 +# export https_proxy=http://localhost:1087 +# export HTTP_PROXY=http://localhost:1087 +# export HTTPS_PROXY=http://localhost:1087 +# export no_http_proxy="localhost;ramwin.com;*.cn" +# export no_https_proxy="localhost;ramwin.com;*.cn" +alias pip="pip3.12" + +HISTFILE=~/.zhistory +HISTSIZE=10000 +SAVEHIST=50000 +setopt inc_append_history diff --git "a/\344\273\277\347\234\237.md" "b/\344\273\277\347\234\237.md" new file mode 100644 index 0000000..b7b4cdb --- /dev/null +++ "b/\344\273\277\347\234\237.md" @@ -0,0 +1,11 @@ +# 仿真 + +* [参考资料](https://zhuanlan.zhihu.com/p/514563099) + +* ESL基础验证,写各个模块的C代码 + +* EDA验证,使用Verilog搭配各种库来验证 +EDA验证比较慢,因为是用CPU来计算,所以我们用硬件来补充验证 + * FPGA: 直接把芯片烧到FPGA看能不能跑起来 + 芯片规模大时需要多个FPGA + * EMULATOR, 仿真波形的加速器 diff --git "a/\344\275\277\347\224\250mdadm\345\210\233\345\273\272raid.md" "b/\344\275\277\347\224\250mdadm\345\210\233\345\273\272raid.md" new file mode 100644 index 0000000..45beb2a --- /dev/null +++ "b/\344\275\277\347\224\250mdadm\345\210\233\345\273\272raid.md" @@ -0,0 +1,116 @@ +# 使用mdadm创建raid + +* [md](https://man7.org/linux/man-pages/man4/md.4.html) +* [mdadm](https://en.wikipedia.org/wiki/Mdadm) + +[教程](https://cloudtuned.hashnode.dev/creating-a-raid-0-volume-in-ubuntu#heading-step-1-install-mdadm) + +## 利用各个磁盘空间创建文件系统 +* 创建文件设备占用各个磁盘空间 +``` +fallocate --length 1G /home/wangx/raid5/a +fallocate --length 1G /home/wangx/raid5/b +fallocate --length 1G /home/wangx/raid5/c +fallocate --length 1G /home/wangx/raid5/d + +# 正式使用时使用各个磁盘的 +fallocate --length 1G /mnt/nvme1/a +fallocate --length 1G /mnt/nvme2/b +fallocate --length 1G /mnt/nvme3/c +fallocate --length 1G /mnt/nvme4/d +``` + +* 把文件变成块设备 +``` +sudo losetup /dev/loop51 /home/wangx/raid5/a +sudo losetup /dev/loop52 /home/wangx/raid5/b +sudo losetup /dev/loop53 /home/wangx/raid5/c +sudo losetup /dev/loop54 /home/wangx/raid5/d +sudo losetup /dev/loop55 /home/wangx/raid5/e +``` + +* [使用mdadm创建磁盘](https://manned.org/mdadm) +``` +sudo mdadm \ + --create --verbose /dev/md55 \ + --level=raid5 \ + --raid-devices=5 \ + /dev/loop51 \ + /dev/loop52 \ + /dev/loop53 \ + /dev/loop54 \ + /dev/loop55 +``` + +* 创建文件系统 +``` +sudo mkfs.ext4 /dev/md55 +sudo mkdir -p /media/md55/ +sudo mount /dev/md55 /media/md55 +``` + +## [增加磁盘](https://askubuntu.com/questions/1351183/how-to-add-a-new-drive-to-a-raid-mdadm-when-that-raid-is-encrypted-luks-an) +``` +fallocate --length 2G f_2g +sudo losetup /dev/loop56 /home/wangx/raid5/f_2g + +# mount前, 5个1G的磁盘,变成了一个3.9G的磁盘 +sudo umount /dev/md55 +sudo mdadm --grow --raid-devices=6 /dev/md55 --add /dev/loop56 +# mount后, 5个1G, 1个2G的磁盘, 变成了3.9G的磁盘 +sudo mount /dev/md55 /media/md55 +``` + +* [重新划分](https://www.itsfullofstars.de/2019/03/how-to-add-a-new-disk-to-raid5/) +``` +sudo umount /dev/md55 +sudo e2fsck -f /dev/md55 +sudo resize2fs /dev/md55 +sudo mount /dev/md55 /media/md55 +# 重新mount后,变成了4.9的磁盘 +``` + +## [损坏磁盘](https://blog.csdn.net/qq_44895681/article/details/105657604) +``` +mdadm -D /dev/md55 # 查看磁盘状态, 当前6个active +sudo mdadm /dev/md55 -f /dev/loop51 # 设置一个磁盘损坏, 还是4.9G文件正常 +sudo mdadm -a /dev/md55 /dev/loop58 # 添加一个新的盘 +sudo mdadm /dev/md55 --remove /dev/loop51 # 删除旧的盘 +``` + +## 扩容 +``` +fallocate --length 2G /home/wangx/raid5/59_2g +fallocate --length 2G /home/wangx/raid5/60_2g +fallocate --length 2G /home/wangx/raid5/61_2g +fallocate --length 2G /home/wangx/raid5/62_2g + +sudo losetup /dev/loop59 /home/wangx/raid5/59_2g +sudo losetup /dev/loop60 /home/wangx/raid5/60_2g +sudo losetup /dev/loop61 /home/wangx/raid5/61_2g +sudo losetup /dev/loop62 /home/wangx/raid5/62_2g +``` + +## 一个一个盘的损坏 +``` +sudo mdadm /dev/md55 -f /dev/loop52 +``` + +## 删除坏盘 +## [重新扩容后,容量只有5.9G](https://documentation.suse.com/sles/12-SP5/html/SLES-all/cha-raid-resize.html) +``` +sudo mdadm --grow /dev/md55 -z max +sudo resize2fs /dev/md55 # 现在有了12G +``` + +## 重新挂载 +``` +sudo mdadm -A /dev/md55 --run /dev/loop57 /dev/loop58 /dev/loop59 /dev/loop60 /dev/loop61 /dev/loop62 +``` + +## [自动挂载](https://www.digitalocean.com/community/tutorials/how-to-create-raid-arrays-with-mdadm-on-ubuntu#creating-a-raid-0-array) +``` +sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf +sudo update-initramfs -u +echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab +``` diff --git "a/\345\206\205\345\255\230.md" "b/\345\206\205\345\255\230.md" new file mode 100644 index 0000000..e48d943 --- /dev/null +++ "b/\345\206\205\345\255\230.md" @@ -0,0 +1,161 @@ +# 内存 +```{toctree} +./海明码算法.md +``` + +## 基础资料 + +## 术语 +* burst buffer 用buffer一次读取128比特数据,然后8比特连续输出16次. 如果write buffer和read buffer冲突了怎么办? +每个chip里都有都有burst buffer. 所以一共1024个bit读取很快 +* [phy](https://zhuanlan.zhihu.com/p/586431901) +链接DDR颗粒和DDR Controller的桥梁,它负责把DDR Controller发过来的数据转换成符合DDR协议的信号,并发送到DDR颗粒; +[比如CPU读写内存了, 需要由phy转化成CK, DQS, 地址信号](https://zhuanlan.zhihu.com/p/32073601963) +处理校准和训练序列 +* [DMA](https://blog.csdn.net/as480133937/article/details/104927922) / Direct Memory Access +一个硬件模块, 用来处理外设存储器之间的传输,释放CPU + +## 参考资料 +* [x] [IECC](https://www.synopsys.com/zh-cn/designware-ip/technical-bulletin/error-correction-code-ddr.html) +* [ ] [DDR基础](https://nr-linux.com/DDR%E5%9F%BA%E7%A1%80) +* [内存里各个阶段的时间概念](https://zhuanlan.zhihu.com/p/597493380) +* [内存基础原理](https://www.youtube.com/watch?v=7J7X7aZvMXQ) +7'23" ddr5 每个memory channel分为channel a和channel b. + * 有32根数据线, 每次传输32Bit的数据 + 每次读写同时发给4个chip, 所以每个chip返回8bit(8'01") + 每个chip里面有8个bankgroup, 每个bankgroup有4个bank(65536 * 8192个比特, 64M) + * 21根地址线(第一次发21bit, 第二次发10bit 选择column) + (外部31根地址线 + 001 bankgroup(一个芯片有8个,所以3比特) + 10 bank(一个bankgroup有4个bank, 所以2比特) + 16比特 65536的哪一行 + 10比特 8192列的哪8列. 最后读出来8bit + * 7个控制信号 +* [ddr4的芯片引脚](https://zhuanlan.zhihu.com/p/113187707) +电源, 接地, 配置 +控制信号, 时钟信号, 地址信号, 数据信号 + +* [ddr5芯片的引脚](https://blog.csdn.net/vagrant0407/article/details/139188259) +* [层级 channel dimm rank chip bank row column](https://blog.csdn.net/qq_50998481/article/details/139067027) +* [内存的page hit](https://www.youtube.com/watch?v=7J7X7aZvMXQ) + +* [升压原理](https://www.youtube.com/watch?v=EhKEqi74yAQ) +* [利用2个二极管,2个电容把电压加倍](https://www.youtube.com/watch?v=1XKMFFTm-UY) +只适合大阻抗的设备, 不然来不及升压,电容就用完了 + +* [snoopimpl](https://www.cs.cmu.edu/afs/cs/academic/class/15418-s19/www/lectures/12_snoopimpl.pdf) + +* 内存的地址对应的物理引脚 +内存row有8192比特, 一次row的激活后可以最多有1024-1次row hit/page hit + + +### 和DDR4的区别 +[参考资料](https://www.youtube.com/watch?v=CG5ontMa8kw) +1. 电压从1.2V => 1.1V +2. DDR4是64bit数据 + 8bitECC +DDR5是32BIT+8BITECC x 2双通道 + +## 内存优化手段 +* [burst buffer](https://youtu.be/7J7X7aZvMXQ?si=0TzCqB8cxA1c00WL&t=1792) +在write driver和read driver上面都加个128in, 8out的burst buffer +column的10个比特拆分成为6 + 4 +所以每次读128比特, 然后连续发送 128/8 = 16次数据. 16就是burst length +* 把bank拆分成1024x1024的block. 这样每次就只激活一个block, 速度快. wordline和bitline更短,充电更快 + +## MMU +* [虚拟地址如何转化成物理地址](https://zhuanlan.zhihu.com/p/492106884) + +## cache一致性 +* [way和set的概念](https://stackoverflow.com/questions/21611058/difference-between-cache-way-and-cache-set) + +## 问题 +* 能否如果读取连续地址同一行,指令就只发送一次. +* 既然一个channel是40通道, 为什么引线有72根. +* DDR里面有缓存吗? 他和L1,L2,L3是否有冲突 +应该没有, 只有buffer支持burst传输 + +## 操作系统如何分配和感知内存 +* [使用位图](https://zhuanlan.zhihu.com/p/452415871) +比如按照4KB分配, 配合位图. 16G / 4KB 需要 4M 个bit. 就是 0.5M 内存 +缺点是申请1G内存时需要查找连续 1G/4K = 256K 个0 + +可以按照 +128M * 8位 +64M * 16位 +32M * 32位 +16M * 64位 +这么分配位图, 申请64M时直接从64M里面申请, 不够就从128里面申请(这就是快速适配法) + +* 快速适配法 +保存各个大小空闲区的链表, 方便下次申请内存. 缺点是进程释放时, 很难查找相邻块(保留各个大小空闲区+所有区块的二叉树就行了吧). 当进程区释放时, 根据二叉树找到进程最后字节的区块,如果是其他进程, 则创建新的空闲区, 否则把空闲区扩大 +* 最佳适配法 +每次找最接近的内存大小, 但是会导致申请后留下很多小内存 +* 首次匹配法 +找到第一个空闲区大于申请长度的位置,申请内存 + +## 页表 +保存虚拟地址到物理地址的内存映射 + +* 页表项 + * 在位不在位1bit + * 保护位(0可写,1只读),访问位,修改位(是否修改过,没修改可以直接丢弃)3bit + * 高速缓存禁止位1bit + +## 交织 +3个内存,需要2bit判断用哪个. 每个内存4字节, 一共12字节. 物理地址需要4bit +0000 内存0 00 ^ 00 = 00 +0001 内存1 01 +0010 内存2 10 +0011 内存0 11 +0100 内存1 01 +0101 内存2 00 +0110 内存0 11 +0111 内存1 10 +1000 内存2 10 +1001 10 ^ 01 11 +1010 10 ^ 10 00 +1011 10 ^ 11 01 + +后面4字节不可能出现. 把前2个比特 && 11一下 +1100 +1101 +1110 +1111 + +## swap +* 参考资料 +[https://www.kernel.org/doc/gorman/html/understand/understand014.html](https://www.kernel.org/doc/gorman/html/understand/understand014.html) + +### 参考资料 +* [内存地址映射](https://www.youtube.com/watch?v=-xtWsQvOcjo) [完整播放列表](https://www.youtube.com/playlist?list=PLTd6ceoshpreE_xQfQ-akUMU1sEtthFdB) + +## 自刷新 +[参考资料](https://digitalasic.design/2021/01/10/ddr-%e5%ad%a6%e4%b9%a0%e6%97%b6%e9%97%b4-part-b-1%ef%bc%9adram-%e5%88%b7%e6%96%b0/) + +### 术语 +* H, L +命令必须是高或者低电平 + +* X, V +可以任意值, 但是X可以悬空, V不可以 + +#### 疑问 +超前延后刷新. 如果延后了数据不丢失,为什么不一直延后 + +### 问题 +* 能否如果读取连续地址同一行,指令就只发送一次. +* 既然一个channel是40通道, 为什么引线有72根. + +## ECC +ECC分类: + +side-band ECC 或 inline ECC。在 side-band ECC 中,ECC 数据存储在单独的 DRAM 上;在inline ECC 中,ECC 数据与实际数据一起存储在同一个 DRAM 上。 +side-band数据和ECC一起读, 所以没有时延损失 + +inline ECC需要读写2次, 一次是数据, 一次是ECC. + +on-die ECC, DDR5有额外的存储器, 只用来ECC存储校验. 但是无法防护DDR信道上的错误, 所以on-die ECC会和side-band ECC 结合使用 + + +## 疑问 +inline ECC中, ECC是和数据一起连续寸的, 还是存在高位地址, 还是存在没一行的最后 diff --git "a/\346\200\273\347\272\277.md" "b/\346\200\273\347\272\277.md" new file mode 100644 index 0000000..1dafef9 --- /dev/null +++ "b/\346\200\273\347\272\277.md" @@ -0,0 +1,80 @@ +# 总线协议 +## 总线仲裁 +* [链式查询](https://blog.csdn.net/Z_CH8648/article/details/134334831) +总线控制部件把总线同意信号(BG) 发下去, 某个设备收到后, 如果有请求就不再往下传(设备如何控制是否往下传的) +* 计数器定时查询 +设备发出总线请求信号, 总线控制器通过计数器发送当前获取总线控制权的设备地址 +每次从0开始, 设备0有最高优先权 +每次从上次数字开始(权重一样) +* 独立请求 +给每个设备添加一个总线请求和总线同意线 + +## 状态表 +* SC: shared clean +clean并不代表没修改过,只是代表我不用负责写回. +被修改过的数据有且只有一个cache是SD状态 + +## 术语 +* RN 请求节点 + * RN-F 全一致性节点. 支持所有snoop事务 + * RN-I IO一致性request节点 + * RN-D: 支持DVM事务的IO一致性节点 + * HN-F: 全一致性Home节点 +* DMA +* Processor +* Memory +* burst +发送一个地址后,返回多次数据. 每次数据是一个beat. 多个数据的组合叫burst +* beat +* WSTRB/strobe signals 用来表明很宽的总线上哪几根有数据 +* WLAST/wlash signal 用来表明当前传输的数据是最后一块 +* channel + 各个channel会复用同一根数据线吗??? + * WRITE ADDR(AW) + * WRITE DATA(W) + * WRITE RESP(B) 表明写入已完成 + * READ ADDR(AR) + * READ DATA(R) + 没有读取完成的RESPONSE因为我们读data时里面已经有了对应的格式 + +## 参考资料 +* [AMBA协议之CHI介绍(一)](https://zhuanlan.zhihu.com/p/6479043066) +* [一种互联系统、数据传输方法以及芯片](https://patentimages.storage.googleapis.com/49/18/b2/687c6de703b9d7/CN116783585A.pdf) + + +* [总线原理](https://blog.csdn.net/Z_CH8648/article/details/134334831) +总线忙(BS)线 +总线请求(BR)线 +总线同意(BG)线 + +* [AXI协议中那些“先不管”信号开篇](https://zhuanlan.zhihu.com/p/718229848) +* [ddr4的芯片引脚](https://zhuanlan.zhihu.com/p/113187707) +电源, 接地, 配置 +控制信号, 时钟信号, 地址信号, 数据信号 + +* [ddr5芯片的引脚](https://blog.csdn.net/vagrant0407/article/details/139188259) +* [AXI协议中多通道依赖关系学习](https://zhuanlan.zhihu.com/p/707551703) +* [AXI信号的依赖关系](https://blog.csdn.net/qq_41394155/article/details/83512986) +* [AXI信号的依赖关系2](https://blog.csdn.net/Michael177/article/details/122266926) +* [AXI信号的依赖关系3](https://mp.weixin.qq.com/s/hPGTRah_3Z9qFco1mr7ggA) +* [AMBA总线(5)—— AXI5新feature](https://www.cnblogs.com/xianyuIC/p/17937602) +* [ ] https://www.youtube.com/watch?v=p5RIVEuxUds +* [ ] https://www.youtube.com/watch?v=A_0ha_6oFDI +* [The AXI Protocol, AXI MM and AXI Streaming Interfaces](https://www.youtube.com/watch?v=Ko3wmIVsOtM) +我们先加一根线传数据, + * 不知道什么时候读这个数据怎么办 +再加一个clk表明什么时候读 + * 不知道什么时候master想写怎么办 +再加一根线代表什么时候valid + * 不知道什么时候slave/subordinate可以写怎么办, 比如buffer满了 +再加一根线代表什么时候slave valid. 目前我们有4根线了 + * 如果要加快读写怎么办 +多加几根data线,最好是8的倍数,因为1字节是8bit + * 有时候只读写1字节,但是有16根线怎么办 +多加byte-enabled signals/strobe signals. 增加1/8根线(比如32bit就要额外4根线表示哪个字节要读写, 不过其实规定好必须从小到大位置写的话, 2bit就可以了) +大部分情况是Processor/DMA到DDR + * 为了加快速度,发送一个地址后,最好返回啊burst + +## 基础知识 +* 环形总线: 大规模场景下时延过高 +* 网格形总线: 面效比低,新增组件时还要新增数据通路,设计复杂 diff --git "a/\346\265\267\346\230\216\347\240\201\347\256\227\346\263\225.md" "b/\346\265\267\346\230\216\347\240\201\347\256\227\346\263\225.md" new file mode 100644 index 0000000..08786e8 --- /dev/null +++ "b/\346\265\267\346\230\216\347\240\201\347\256\227\346\263\225.md" @@ -0,0 +1,40 @@ +# 海明码算法设计 +https://blog.csdn.net/zhangyanfei01/article/details/136386142 + +第一个比特位做奇偶校验 +第2到第4个比特位当作列校验区分8列 +第5个到第7个比特位当作行校验区分8行 + +如果只有一个数据比特错了, 那么第一个比特就错误, 列比特和行比特分别有一个校验位不正确. +如果有2个数据比特错了, 那么第一个比特正确, 列比特和行比特至少有一组存在2个比特不正确 +如果3比特出错了, 那么第一个比特错误, 错误3比特构成的矩形的另外一角会被修复 + +但是理论上8个比特应该找到256种情况. N代表校验比特数 +``` +N=64, 全正确1, 1个错误64, 2个错误 64*63/2 == 2081种情况, 全正确需要12个比特 +``` + +类似海明码, 我把数据变成立方体 4x4x4. 没意义, 因为利用二分法查找已经是最快的 +``` +2**K >= 比特数 + K + 1 +``` +64比特情况下, K最小为7, 所以ECC存在1个比特冗余 + +``` +第一个比特代表总体 +第二个比特代表第1,2层 +第三个比特代表第1,3层 +第四个比特代表第1,2列 +第五个比特代表第1,3列 +第六个比特代表第1,2行 +第七个比特代表第1,3行 +``` + +如果出现2个比特(层1,行1,列1, 层2,行3,列1) 错误. +那么第一个比特是正确的. +第二个比特正确的 +第三个比特错误的 +第四个比特错误的 +第五个比特错误的 +第六个比特错误的(1,2有) +第七个比特正确的(2行+4行 或者 1行+3行) diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206.md" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206.md" new file mode 100644 index 0000000..8249790 --- /dev/null +++ "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206.md" @@ -0,0 +1,298 @@ +# 计算机组成原理 +Package、Module、Tile、 Die、Core、Thread +package: 封装好的一个 + +Tile: CPU分几个区块, 不同的区块可以用不同的制程 +比如IO Tile就用6nm, CPU Tile用3nm + +```{toctree} +./内存.md +./总线.md +``` + +## 资料 +* https://www2.imm.dtu.dk/~masca/chisel-book-chinese.pdf +* https://zhuanlan.zhihu.com/p/681417344 + +## [ROB](https://www.youtube.com/watch?v=TnxJA6uyP7Y) +[HPCA](https://www.youtube.com/playlist?list=PLAwxTw4SYaPmqpjgrmf4-DGlaeV0om4iP) +Reorder Buffer +用一个表,包含[REG,VAL,DONE](https://www.youtube.com/watch?v=TnxJA6uyP7Y). +问题后面如果有需要回退时怎么知道回退到哪个 +如果后面有要用到ROB里面的REG, 难道要每行都去查询一遍吗 +ROB不区分线程, 那线程切换时,CPU是不是要等待ROB全部done + +## 术语 +* [retention CG PG](https://www.eet-china.com/mp/a300277.html) +PG: 关了电源, 没有静态功耗和动态功耗, 但是寄存器信息丢失导致无法 +CG: 关了时钟, 少了很多动态功耗 +retention: 在PG基础上增加几个寄存器,避免无法恢复 + +* DIE +CPU DIE, IO DIE +共享一系列资源的逻辑电路. +一颗cpu叫cpu package. 里面至少1个die, 可能有多个die. +每个die都是晶圆上切割出来的矩形颗粒 +一个die大概在6mm到10mm + +* 存储单元 +每个存储单元的地址是唯一的 +位宽,一个存储单元保存了多少个字节 + +* 地址总线 +> CPU要想访问某个存储单元,必须要通过地址总线给出相应的 地址, 因此如果地址总线的宽度为N,则CPU能管理的存储单元数最多为2的N次方个 +* MAR(Memory Address Register 存储地址寄存器) +CPU通过地址总线发来的地址会存放在MAR里面 +* 数据总线 +存储单元位宽的整数倍 +* MDR(Memory Data Register 存储器数据寄存器) +* 控制总线 +接受来自CPU的读写传输完成等信号 +* CPU +包含控制器和计算器 +* 控制器 +* 指令寄存器(IR Instruction Register) +正在执行或者即将执行的指令 +* 程序计数器(PC) +吓一跳指令的存储单元位置,具有自动增量计数的功能 + +* RCU +* Page Fault +CPU读取page table是, 发现内存地址对应的地址在磁盘上 + +* PageTable +保存在内存上的各个进程的VPN(virtual page number)到PPN(physical page number)的转化 + +* TLB/translation lookaside buffer +因为每次读取pagetable都很慢, 所以有了tlb. 如果hit, 在1cycle内就能返回结果. 如果miss, 需要10~100cycle +0.01%~1%的miss rate(20%~40% for sparse application) + +* mmu/memory management unit +负责地址转化和raise page fault的硬件 + +* DMA +当Page Fault时,需要等待很久, DMA就负责后台异步把内存写入磁盘 +数据写入也是用DMA来控制的 + +* COW/copy on write +进程fork或者起来的时候, 我们把数据段设置成readonly. 当有写操作时,才会触发page fault. 然后才会写. + * 同一个进程里能否利用这个属性, 创建userlist, 改的时候才复制user出来? 有点困难,相当于把用户信息从内存转移到TLB并且改任意一个字节都导致要COW + +* [PLL/Phase Locked Loop锁相环](https://www.youtube.com/watch?v=YtlwIFsiWtE) +用来增加晶振的频率 + + * 鉴相器 + 输入1位晶振的电压, 输入2为后面VCO的电压. 输出为晶振电压降高,但VCO电压低时, 为高电压. 这样VCO频率就变大, 知道VCO频率和输入一致 + + * 低通滤波器 + 鉴相器出来电压时矩形波, 利用这个变平滑后给VCO + + * VCO/Voltage Controlled Oscillator 压控振荡器 + 电压越大, 频率越大. 哪怕电压变压很小, 频率变化也很大 + + * 如何翻倍呢 + 在VCO和鉴相器之间添加分频器 + + * 如何分频呢? 用计数器取模 + +### [TLB](https://www.youtube.com/watch?v=A9WLYbE0p-I&t=858s) +Translation lookaside buffer +每次都通过page table查找一个地址对应的物理地址太慢了,所以在cpu内部添加tlb来加快地址转化速度 + +* 基础概念 +一般有个CPU有2个TLB, 一个ITLB给指令用, 一个DTLB给data用(一般4000个entries) +hittime 0.5 ~ 1 cycle(为什么小于1我不太理解) +miss penalty: 10~100 cycle +miss rate: 0.01% - 1% + +1. TLB的硬件原理 +2. 多个进程能否使用同一个TLB或者PageTable避免进程切换的开销 +3. 当page table满了的时候, 能否优先删除clean的, 而不是LRU的 +4. TLB应该和进程直接相关的, 和cache能否做在一起呢 + +* 案例 +比如32比特的虚拟地址, 30比特的物理地址. pagesize是4kb(大部分都是4kb), 所以12bit是offset. 20bit要映射到18bit. +每个program需要`2**20`行, 就是1M, 每行38bit(20bit虚拟地址用index来做, 18bit的物理地址+权限大概4字节)就是4M左右. 50个程序就会有200M内存用来保存page tables, 这个太多了 +另一种说法是既然我们有pagetable了,直接索引当作虚拟地址. 所以每个entry只需要保存物理地址20bit + 权限(大概4字节) + +* 经常分配后,内存碎了怎么办 +* page fault +当程序的page不在内存里的时候, 把最近不用的page写回磁盘, 从磁盘读出数据后修改page table. 这时候DMA上场修改, cpu做其他事 + + +#### [多层结构](https://www.youtube.com/watch?v=Z4kSOv49GNc) +linux现在有5层 +一个进程2**32字节内存, 需要2**20行TLB, 我们拆分成2**10个chunk, 每个chunk 2**10. chunk也改成tlb +这样只有level1的page table需要保存在内存里 +访问 0x12345678 (最后678是offset不用管) +在 level 1 pagetable里找到 0x12345对应的 level 2 pagetable 的index是0x0010 +然后在level 2 pagetable里找到index=0x0010的数据, 她的物理地址是0x4321 +[示例](https://youtu.be/Z4kSOv49GNc?si=ZrpTl2BUwouCzW2r&t=336) +把前面的10bit当作1st page table的索引. 中间10bit当作level 2的page table的索引 +一个程序只要要有2**10个entry(4kb)保存level1 pagetable 和 4kb的level 2的pagetable. 剩下的都可以放入磁盘 + +## 内存 + +### 术语 +* burst buffer 用buffer一次读取128比特数据,然后8比特连续输出16次. 如果write buffer和read buffer冲突了怎么办? +每个chip里都有都有burst buffer. 所以一共1024个bit读取很快 + +### 参考资料 +* [层级 channel dimm rank chip bank row column](https://blog.csdn.net/qq_50998481/article/details/139067027) +* [内存的page hit](https://www.youtube.com/watch?v=7J7X7aZvMXQ) + + +#### 虚拟地址每次都需要转换怎么办 +* 使用虚拟地址转化后才使用cache +每次都转化太麻烦 +* cache直接保存虚拟地址 +会导致进程切换无法隔离 + +#### VIPT +virtual indexed, physically tagged +通过虚拟地址查找cache和tlb, 查到后对比cache里的physical address的tag和tlb的地址是否一致. 一致就cache hit +比如4KB(12bit作为offset了, cache是64字节(10bit). 但是因为前面的物理地址用来做比较了, 所以cache只能用后面的12bit, 所以 +最大的cache size只能是4kb + +#### 术语 +* offset +比如pagesize设置成4kb(12bit), 那么保存内存映射时最后12bit不考虑 + +* virtual page number +虚拟地址(比如32bit), 去除后面pagesize(12bit)后剩下的20bit就是虚拟pagenumber + +* physical page number +物理地址的前(18bit) + +* 内存的地址对应的物理引脚 +内存row有8192比特, 一次row的激活后可以最多有1024-1次row hit/page hit + + +### 内存优化手段 +* [burst buffer](https://youtu.be/7J7X7aZvMXQ?si=0TzCqB8cxA1c00WL&t=1792) +在write driver和read driver上面都加个128in, 8out的burst buffer +column的10个比特拆分成为6 + 4 +所以每次读128比特, 然后连续发送 128/8 = 16次数据. 16就是burst length +* 把bank拆分成1024x1024的block. 这样每次就只激活一个block, 速度快. wordline和bitline更短,充电更快 + +### 问题 +* 能否如果读取连续地址同一行,指令就只发送一次. + + +## ROM +* [bios的原理](https://www.youtube.com/watch?v=h_kAcVuJEm0) +* ROM Matrix. +* multiplexer(2**n个输入, 使用n个控制来决定哪个是输出) +* demultiplexer(反过来,根据控制决定输出到哪个output line) +* Decoder: +DeMux/demultiplexer without and data input + + +## [内核态](https://learn.lianglianglee.com/%E4%B8%93%E6%A0%8F/%E9%87%8D%E5%AD%A6%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F-%E5%AE%8C/14%20%20%E7%94%A8%E6%88%B7%E6%80%81%E5%92%8C%E5%86%85%E6%A0%B8%E6%80%81%EF%BC%9A%E7%94%A8%E6%88%B7%E6%80%81%E7%BA%BF%E7%A8%8B%E5%92%8C%E5%86%85%E6%A0%B8%E6%80%81%E7%BA%BF%E7%A8%8B%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB%EF%BC%9F.md) +## 计算机组成原理 + +### 第一讲 计算机基本结构 +* [104 计算机结构的简化模型][104] +* [105 计算机执行指令的过程][105] + 1. PC(0001) - 内部总线 - MAR: 告诉存储器,我要读那个地址的指令 + 2. MAR - 地址总线 - 存储器MAR; CPU控制电路(READ) - 控制总线 - 存储器控制逻辑 + 3. 存储单元(0001对应的数据10101010) - 存储器MDR; 存储器控制逻辑(READY) - 控制总线 - CPU控制电路; 存储器MRD - 数据总线 + 4. CPU的MRD - 内部总线 - IR; PC+=1; 至此,IR内存放了10101010,取指完毕 + +[104]: https://www.coursera.org/learn/jisuanji-zucheng/lecture/1wVRC/104-ji-suan-ji-jie-gou-de-jian-hua-mo-xing +[105]: https://www.coursera.org/learn/jisuanji-zucheng/lecture/8Xyeu/105-ji-suan-ji-zhi-xing-zhi-ling-de-guo-cheng + + +## 高性能计算机 +### 参考资料 +* [youtube播放列表](https://www.youtube.com/playlist?list=PLAwxTw4SYaPmqpjgrmf4-DGlaeV0om4iP) + +### 术语 +* 动态功率 +``` +P = 1/2 * C * V**2 * f * a # 电容 * 电压的平方 * 频率 * 活跃系数 +``` +* [静态功率](https://www.youtube.com/watch?v=zN5lg91v40g&list=PLAwxTw4SYaPmqpjgrmf4-DGlaeV0om4iP&index=16) +根据静态功率和动态功率, 低负载情况下, 可能高压状态下反而导致功耗下降 + +### 流水线 +当前30到40级流水线性能最好. 但是能耗比较高. 所以最后实际生产一般是10到15级 +* [冲突处理](https://www.youtube.com/watch?v=x6vuFvSg2Uo&list=PLAwxTw4SYaPmqpjgrmf4-DGlaeV0om4iP&index=78) + 1. flush + 2. stall + 3. 修复之前指令的数据 + * forwarding 直接把alu的数据传给下一跳指令的alu + +### 分支预测 +* [HPCA-96][HPCA-96] +为什么我们需要高准度的预测 +* 通过当前PC + next PC + * 如何知道当前指令是不是branc(还在fetch阶段不清楚) + * 如何知道是否需要跳转 + * 跳转到哪(不知道offset) +``` +while (x < 0) { // 分支判断x, 大部分都<0 + x--; + ... +} +``` + +#### BTB/Branch Target Buffer +当PC在prefetch后,查询BTB里面的信息. +当PC执行完后, 确认BTB里面是否正确, 不正确就刷新 +* BTB应该多大呢 +因为fetch后不知道是不是分支, 所以程序里每个指令都要保存到BTB +如果是循环, 循环里有多少个指令, BTB就要有多少行 +我们把PC的最后不一致10位当作index, (不一致: 比如指令4字节对齐,PC的最后2bit必定是0, 所以用PC[-12:-2]当作index +* BHT/Branch History Table 应该存什么 + 1. 1bit保存是不是分支跳转, 是分支并且跳转才去查看BTB +最简单的,我觉得应该保存Next PC就行. 预测错了就修改. +或者保存jump的位置, 比如+4(不跳转)或者+200(跳转), 这样就不用4字节长了 +* 1-BIT预测的缺点 + 1. 不适用于跳转不跳转差不多的情况 + 2. 不适用于指令比较少的循环(进入和退出必定2次mis prediction) + +* 2-BIT PREDICTOR(2BP/2BC) +![内容](https://youtu.be/zhyEYt2uylQ?si=DyfzVQfH-8fkMB_9&t=290) +第一个比较是PREDICTION BIT. 第二个是我们是否确认第一个预测正确 +00 STRONG NOT_TAKEN +01 WEAK NOT_TAKEN +10 WEAK TAKE +11 STRONG TAKEN + +* HISTORY-BASED PREDICTORS + +第一个比特用来表明上次是T/N, 应该用后面那个predictor +后面的是2bit Predictor. + +* 如何减少BHT的用量 +对于NNNT, 因为有2^4种情况, 所以我们需要2^4 counter. 但只有4种counter用到了(NNNT, NNTN, NTNN, TNNN) +我猜想我们可以减少entry的个数, 多个情况共用2BC, 怎么共用呢? 我觉得采用后面2个NT做索引 +没想到实际上是根据PC找到PHT后, 再用PC和PHT的值XOR来差BHT + +## 问题 +* [ ] 下面这个代码,是否应该把通用的计算放前面 +``` +c = d + e # 能不能把这行代码放入分支内, 这样如果预测失败, 只用flush少量的流水线 +if (x>0): + # c = d + e + a = c + 1 +else: + # c = d + e + a = c + 2 +e = f + g # 能不能先判断if, 然后执行这条命令, 判断完成后才执行 a = c + 1 或者 a = c + 2 +``` +* [ ] BTB对每个指令都预测,能否不在prefetch后就预测, 而是decode以后, 发现是branch才预测. +这样一能减少预测次数,节能. 二能极大地减少BTB的尺寸. +缺点就是真的预测的时候, 会慢一拍(prefetch到decode) + +## CPU生产过程 +* [youtube](https://www.youtube.com/watch?v=LcGGI2BIymg) +总体不错, 但是金属线怎么连的不具体 +* [youtube](https://www.youtube.com/watch?v=okCUq_yWVxk) +金属连线也是一样的. 多加几层 + +[HPCA-96]: https://www.youtube.com/watch?v=I5vDaDk01D0&list=PLAwxTw4SYaPmqpjgrmf4-DGlaeV0om4iP&index=96 + +## cache +[L3 partitioning](https://developer.arm.com/documentation/101322/0102/Overview/L3-cache/L3-cache-partitioning) diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_205805.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_205805.jpg" new file mode 100755 index 0000000..1502f88 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_205805.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_225727.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_225727.jpg" new file mode 100755 index 0000000..c289717 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211105_225727.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211106_111258.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211106_111258.jpg" new file mode 100755 index 0000000..8a46677 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211106_111258.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174007.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174007.jpg" new file mode 100755 index 0000000..939ebc3 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174007.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174138.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174138.jpg" new file mode 100755 index 0000000..0f9d65a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174138.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174958.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174958.jpg" new file mode 100755 index 0000000..8ee88bb Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/IMG_20211107_174958.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-21-15-35-885_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-21-15-35-885_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..ba775a2 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-21-15-35-885_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-32-54-386_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-32-54-386_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..7105e1a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-32-54-386_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-02-631_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-02-631_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..7be93a3 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-02-631_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-57-921_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-57-921_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..236c046 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-34-57-921_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-44-43-363_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-44-43-363_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..ee4ba2a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-44-43-363_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-51-45-707_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-51-45-707_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..c7b034e Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-51-45-707_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-08-624_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-08-624_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..270b7c8 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-08-624_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-25-204_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-25-204_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..ae4fd23 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-53-25-204_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-54-11-466_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-54-11-466_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..399023f Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-22-54-11-466_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-23-02-57-816_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-23-02-57-816_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..1f1224a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-05-23-02-57-816_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-07-17-41-59-132_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-07-17-41-59-132_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..c6d7e9d Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-07-17-41-59-132_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-45-09-124_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-45-09-124_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..dd2c569 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-45-09-124_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-18-191_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-18-191_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..d201f8a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-18-191_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-54-665_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-54-665_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..b41d53a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-54-54-665_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-25-165_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-25-165_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..98be0ce Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-25-165_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-39-008_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-39-008_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..354747d Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-39-008_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-45-355_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-45-355_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..831c21a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-55-45-355_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-56-48-645_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-56-48-645_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..f55efb0 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-56-48-645_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-57-44-195_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-57-44-195_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..140313a Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-57-44-195_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-13-313_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-13-313_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..d7c057d Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-13-313_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-50-830_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-50-830_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..c5ccbc4 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-10-19-58-50-830_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-34-34-609_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-34-34-609_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..fb9fa6d Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-34-34-609_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-35-13-554_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-35-13-554_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..f6559dc Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-35-13-554_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-41-233_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-41-233_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..8e918d6 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-41-233_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-51-169_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-51-169_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..ed09441 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-36-51-169_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-37-41-192_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-37-41-192_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..158fa0c Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-37-41-192_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-41-06-906_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-41-06-906_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..37bc90b Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-11-08-41-06-906_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-39-03-639_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-39-03-639_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..9efedb1 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-39-03-639_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-30-885_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-30-885_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..fcd1923 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-30-885_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-50-781_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-50-781_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..99c2c14 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-40-50-781_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-41-22-163_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-41-22-163_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..9724ad2 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-41-22-163_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-42-39-960_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-42-39-960_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..160adb6 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-12-08-42-39-960_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-48-06-523_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-48-06-523_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..aa0a35b Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-48-06-523_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-40-439_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-40-439_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..7c42cbd Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-40-439_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-52-800_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-52-800_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..006987d Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-25-08-59-52-800_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-28-18-38-06-571_tv.danmaku.bilibilihd.png" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-28-18-38-06-571_tv.danmaku.bilibilihd.png" new file mode 100755 index 0000000..97d5048 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-11-28-18-38-06-571_tv.danmaku.bilibilihd.png" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-21-47-23-977_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-21-47-23-977_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..9f91257 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-21-47-23-977_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-01-40-432_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-01-40-432_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..b0db62b Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-01-40-432_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-02-25-508_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-02-25-508_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..7796d4f Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-02-25-508_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-31-439_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-31-439_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..f877435 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-31-439_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-41-231_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-41-231_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..67abb0e Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-41-231_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-53-086_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-53-086_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..2b6168b Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-07-53-086_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-11-232_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-11-232_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..f40345c Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-11-232_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-58-008_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-58-008_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..6ab0742 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-09-58-008_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-28-36-310_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-28-36-310_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..f7b1747 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-28-36-310_tv.danmaku.bilibilihd.jpg" differ diff --git "a/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-31-00-446_tv.danmaku.bilibilihd.jpg" "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-31-00-446_tv.danmaku.bilibilihd.jpg" new file mode 100755 index 0000000..34593a1 Binary files /dev/null and "b/\350\256\241\347\256\227\346\234\272\347\273\204\346\210\220\345\216\237\347\220\206/Screenshot_2021-12-05-22-31-00-446_tv.danmaku.bilibilihd.jpg" differ