优化思维【4】Bash for 循环

常规教材

Bash 循环有三种写法。

1. 类 C 语言语法

1
2
3
4
5

for ((i = 1; i <= 10000000; ++i))
do
echo $i
done

2. for in 语法

1
2
3
4
for i in {1..10000000}
do
echo $i
done

3. 使用外部命令 seq

1
2
3
4
for i in `seq 1 10000000`
do
echo $i
done

分析

这三种方法中,性能最好的是第一种,最差的是第三种。

方法 1 是语言层面的循环语法,循环会立刻开始,而后两种,作为对比,并不会立刻开始!

方法 2 中的 {1..10000000} 会产生一个 1 到 10000000 的序列,然后再开始循环。

方法 3 中的 seq 1 10000000 是调用 seq 产生一个 1 到 10000000 的序列,然后再开始循环。涉及到外部进程调用和管道传递,所以比方法 2 更慢。

总结

  • 方法 1 写起来最麻烦,性能却是最好的。“做一件事,有很多种方式”,有时候不是好事,有对比,就有伤害……优化往往是和人性作对!

  • 语言原生的方法一般比调用外部命令好。

优化思维【3】消除没必要步骤

故事

四月底给 EOSIO / eos 提了一个优化 MongoDB 插件性能的 PR,被连续感谢好几个 Release

分析

原先的流程:fc::variant -> JSON string -> BSON,实现起来很简单,因为 JSON 是很常见的,fc::variant 和 BSON 都有到 JSON 的转化,所以实现代码很简单,一行两个函数。

但数据大时,性能问题就暴露了,这个过程先把 fc::variant 对象序列化为 JSON 字符串,然后反序列化到 BSON 对象。两步都是 CPU 密集型操作,由于 nodeos 及其插件暂时对多核支持不好,导致单核跑爆。

两个过程都要用递归实现,调用栈可能很深。调用函数可能有入栈出栈的消耗,有一种优化思路正是用 inline 减少函数的频繁调用

回归到本质,fc::variant 和 BSON 都是对象,应该直接转化才对。只是实现起来就不是一行能搞定的。先挑简单的方式实现,后期再优化,这是一种挺常规的做法。

优化思维【2】有符号和无符号的本质区别

做题

以下代码打印什么?

1
2
3
4
5
6
7
auto count = sizeof (int);
if (count > -1) {
std::cout << "> -1";
}
else {
std::cout << "<= -1";
}

答案是:<= -1,因为 sizeof (int) 是无符号的,把 auto 改为 int 则结果是 > -1

本质论

当我们声明 unsigned/signed int count 时,unsigned/signed 是变量 count 的使用属性,int 是其容量属性。

所谓使用属性,就是当它存在寄存器或内存时,不管是 unsigned 还是 signed 本质是一样的,但对它进行访问时,就区别对待。

比如对 count 进行加法,unsigned 时用的是 ADD 指令,signed 时用的是 ADC 指令,其余减乘除也都类似地使用不同指令。

再来一个问题:把一个变量保存到文件里,再读出来,怎么知道它是有符号还是无符号?

答案是:如果你不在序列化时考虑符号,则反序列化时,无法知道原来的符号,把它赋值给什么类型的变量它就变成什么类型。

这也是 JSON 文本转对象后,要自己选择数据类型的原因,因为 JSON 文本没表示符号的语法。

结论

优化思路:理解本质,就能了解限制和优化方向。

优化思维【1】字符串去空格

In place 版本

传入的字符串将被改变。

为方便复用,一般会实现 ltrim 和 rtrim 两个函数,然后 trim 函数调用这两者实现。

  • ltrim:从 str 头部开始找到非空格字符,偏移量记为 offset,将 str 左移(move)offset 个字符。

  • rtrim:从 str 尾部向头部找到非空格字符,偏移量记为 offset,将 str 截断为 offset。

一个想当然的实现:

1
2
3
4
trim(str) {
ltrim(str)
rtrim(str)
}

假设 str 是 x 个空格 + y 个非空格 + z 个空格,则以上代码需要把 y + z 个字符向左移动 x 个位置。

更好的实现是:

1
2
3
4
trim(string& str) {
rtrim(str)
ltrim(str)
}

由于先截断,剩 x + y,再去左移,只需要把 y 个字符左移 x 个位置。

优化思路:尽量减少复制,调整顺序也是优化手段。

Copy 版本

传入的字符串不会被改变,返回一个新的字符串。

一个复用前面代码的实现:

1
2
3
4
5
6
string trim_copy(string str) {
// str is a copy
rtrim(str)
ltrim(str)
return str
}

这个版本需要复制 x + y + z 个字符,ltrim 和 rtrim 里面都有找偏移量的代码可以复用,直接找到 y 个非空格字符是起点和终点,复制这 y 个字符就好了。

1
2
3
4
5
6
string trim_copy(const string& str) {
// str is a copy
l = lfind(str)
r = rfind(str)
return str[l, r]
}

优化思路:尽量减少复制。

move

strlen、strcpy、memmove 这类函数,都有一个优化思路:机器字长对齐,一次处理一个机器字。对于长字符串,效果显著。

优化思路:针对硬件特征调整策略。

修复 Clang 编译错误:error: expected unqualified-id

问题

今天编译 EOSIO/eos 出现一些 error: expected unqualified-id

环境

  • 操作系统:macOS Mojave
  • 编译器:AppleClang 10.0.1.10010046
  • SDK:MacOSX10.14.sdk
  • Boost:1.69.0(1.67.0 也有问题,干脆用这个版本)

验证问题

1
2
3
4
5
6
7
8
9
#include <signal.h>

int main() {
::sigset_t sigset;

::sigemptyset(&sigset);
::sigaddset(&sigset, SIGCHLD);
return 0;
}

编译输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Scanning dependencies of target signal
[ 50%] Building CXX object CMakeFiles/signal.dir/signal.cpp.o
/Users/umu/umutech/macos-cpp/source/study/posix/signal/signal.cpp:6:5: error: expected unqualified-id
::sigemptyset(&sigset);
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/signal.h:125:26: note: expanded from macro 'sigemptyset'
#define sigemptyset(set) (*(set) = 0, 0)
^
/Users/umu/umutech/macos-cpp/source/study/posix/signal/signal.cpp:7:5: error: expected unqualified-id
::sigaddset(&sigset, SIGCHLD);
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/signal.h:122:31: note: expanded from macro 'sigaddset'
#define sigaddset(set, signo) (*(set) |= __sigbits(signo), 0)
^
2 errors generated.
make[2]: *** [CMakeFiles/signal.dir/signal.cpp.o] Error 1
make[1]: *** [CMakeFiles/signal.dir/all] Error 2
make: *** [all] Error 2

解决

去掉 sigemptysetsigaddset 前面的 :: 即可。因为他们是宏,宏都是全局的,用 :: 修饰反而错了,严格!

Boost 开发分支上已经修复:

https://github.com/boostorg/process/blob/develop/include/boost/process/detail/posix/wait_for_exit.hpp#L60

https://github.com/boostorg/process/blob/develop/include/boost/process/detail/posix/wait_group.hpp#L65

纯数字 EOS 账号

作者: UMU @ MEET.ONE 实验室

问题

2018 年最后一个工作日,智能合约开发小哥哥遇到一个奇怪的现象:某个账号给我们合约转账,在 EOS 浏览器上都可以找到记录,但用 cleos get table 在合约的 RAM 里找却找不到!

解决

观测

了解具体情况后,注意到两个事实:

  1. 只有某个特定账号有问题,其它账号很正常。

  2. 那个有问题的账号是纯数字的。

这是 EOS 账号解析的问题,UMU 曾经给 EOS 提过一个相关的 issue:get_table_by_scope parameter lower_bound is NOT properly converted, cause enumeration dead loop #5824,里面有问题产生原因和解决方案。

原因

eosio::name 本质是一个 uint64_t 数字的 base32 编码,编码形式是为了方便人类记忆。举个例子:

shengxiaokai 本质上是 14075216089888066784 (0xc3553675c6a40ce0)

cleos get table 在解析账号时,兼容了这两种表达形式,所以 14075216089888066784shengxiaokai 是等价的。

但本身是纯数字的账号可就有歧义了,比如 313131313131 是当成一个 uint64_t 解释,还是当成 base32?很不巧,解析代码是优先当成 uint64_t 解释的。

解决方案

给纯数字 EOS 账号加上个空格后缀,比如 111122223333 可以改为 "111122223333 "

改进 EOSIO MongoDB 插件对分片集群的插入性能

作者: UMU @ MEET.ONE 实验室

问题

为了保证 MongoDB 服务器的容量足够应对未来发展,我们做了分片,但经过对比测试,发现每隔 15 分钟左右,nodeos 就会报错,并优雅退出。

查看了社区的 issues 发现有类似情况:mongodb shard: line 870, code 61, generic server error

解决

定位代码

反复测试发现,总是同一个地方抛出异常:

1
2
3
4
5
6
7
8
9
10
11
// insert action_traces
if( write_atraces ) {
try {
if( !bulk_action_traces.execute() ) {
EOS_ASSERT( false, chain::mongo_db_insert_fail,
"Bulk action traces insert failed for transaction trace: ${id}", ("id", t->id) );
}
} catch( ... ) {
handle_mongo_exception( "action traces insert", __LINE__ );
}
}

插入数据的代码很多,但就这个地方报错,说明 action_traces 表有特殊性。

分析异同

action_traces 的 shard key 被定义为 _id,而其他没报错的表并不是 _id。

理论

批量插入时,_id 是有单调递增性的,根据官方文档
Avoid Monotonic Throttling,需要降低单调递增性,才能使批量插入均匀分散到各个 shard 上。

成果

(#6498) Fix cluster writes for mongo DB

EOSIO 1.5.0 MongoDB 插件搭配 MongoDB 4.0.4

问题描述

在前文《为 EOSIO MongoDB 插件搭建高可用集群》中,我们使用了 MongoDB 4.0.4,如果直接配套 EOSIO 1.5 版本,MongoDB 插件用的 MongoDB C Driver 与 MongoDB 4.0.4 是不完全兼容的。

  • EOSIO 1.5 指定的 MongoDB 版本是 3.6.3;

  • MongoDB 4.0 的客户端需要 MongoDB C Driver 1.11.0,而 EOSIO 1.5 用的是 1.10.2。

参考:Release Notes for MongoDB 4.0

改进方案

修改 eos/scripts/eosio_build_${SYS_NAME}.sh,其中 SYS_NAME 是系统名字,以 macOS 为例,应该改的是 eos/scripts/eosio_build_darwin.sh

  • 把 mongo-c-driver 版本改到足够高,比如 1.13.0,即把脚本里的下载链接 https://github.com/mongodb/mongo-c-driver/releases/download/1.10.2/mongo-c-driver-1.10.2.tar.gz 改为 https://github.com/mongodb/mongo-c-driver/releases/download/1.13.0/mongo-c-driver-1.13.0.tar.gz

  • 把 mongo-cxx-driver 版本改到足够高,比如 3.4.0,可以直接把脚本里的 git clone https://github.com/mongodb/mongo-cxx-driver.git --branch releases/v3.3 --depth 1 改为 git clone https://github.com/mongodb/mongo-cxx-driver.git --branch releases/stable --depth 1

  • Ubuntu 操作参考:

1
2
3
4
5
6
7
8
9
10
11
12
sed -i 's/releases\/v3.3/releases\/stable/;s/1\.10\.2/1\.13\.0/g' scripts/eosio_build_ubuntu.sh

# 编译前
grep "Version:" /usr/local/lib/pkgconfig/libmongocxx-static.pc
Version: 3.3.2-pre

# 编译
./eosio_build.sh

# 编译后
grep "Version:" /usr/local/lib/pkgconfig/libmongocxx-static.pc
Version: 3.4.0

然后编译、安装 eos。

参考:

mongo-c-driver 1.13.0

MongoDB C++11 Driver 3.4.0

注意事项

以上方法不适用于 v1.7.0,新版 eos 已经使用新版 mongo-c-driver 和 MongoDB C++11 Driver,唯一需要改的是 eos/scripts/eosio_build.sh 的这行:

1
export MONGODB_VERSION=4.0.6 #3.6.3

为编译 EOSIO 降级 boost 到 1.67

问题

目前 EOSIO 1.5 依赖的 boost 版本为 1.67,但最新的 boost 是 1.68,如果不小心用 brew upgrade 把 boost 升级到最新,则 EOSIO 代码将无法顺利编译。

解决

不必删除 1.68 版本,当之前安装过 1.67,再安装 1.68 时,其实两者是同时存在的,只是系统目录下的链接是指向最新版本而已。只要把链接改回 1.67 即可。

以下脚本适用于 macOS Mojave 系统,其它系统请自行做相应修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
ln -s /usr/local/include/boost /usr/local/Cellar/boost/1.67.0_1/include/boost 

ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_atomic-mt.a /usr/local/lib/libboost_atomic-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_atomic-mt.dylib /usr/local/lib/libboost_atomic-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono-mt.a /usr/local/lib/libboost_chrono-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono-mt.dylib /usr/local/lib/libboost_chrono-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono.a /usr/local/lib/libboost_chrono.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_chrono.dylib /usr/local/lib/libboost_chrono.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container-mt.a /usr/local/lib/libboost_container-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container-mt.dylib /usr/local/lib/libboost_container-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container.a /usr/local/lib/libboost_container.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_container.dylib /usr/local/lib/libboost_container.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_context-mt.a /usr/local/lib/libboost_context-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_context-mt.dylib /usr/local/lib/libboost_context-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract-mt.a /usr/local/lib/libboost_contract-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract-mt.dylib /usr/local/lib/libboost_contract-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract.a /usr/local/lib/libboost_contract.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_contract.dylib /usr/local/lib/libboost_contract.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine-mt.a /usr/local/lib/libboost_coroutine-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine-mt.dylib /usr/local/lib/libboost_coroutine-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine.a /usr/local/lib/libboost_coroutine.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_coroutine.dylib /usr/local/lib/libboost_coroutine.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time-mt.a /usr/local/lib/libboost_date_time-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time-mt.dylib /usr/local/lib/libboost_date_time-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time.a /usr/local/lib/libboost_date_time.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_date_time.dylib /usr/local/lib/libboost_date_time.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_exception-mt.a /usr/local/lib/libboost_exception-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_exception.a /usr/local/lib/libboost_exception.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_fiber-mt.a /usr/local/lib/libboost_fiber-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_fiber-mt.dylib /usr/local/lib/libboost_fiber-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem-mt.a /usr/local/lib/libboost_filesystem-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem-mt.dylib /usr/local/lib/libboost_filesystem-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem.a /usr/local/lib/libboost_filesystem.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_filesystem.dylib /usr/local/lib/libboost_filesystem.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph-mt.a /usr/local/lib/libboost_graph-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph-mt.dylib /usr/local/lib/libboost_graph-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph.a /usr/local/lib/libboost_graph.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_graph.dylib /usr/local/lib/libboost_graph.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams-mt.a /usr/local/lib/libboost_iostreams-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams-mt.dylib /usr/local/lib/libboost_iostreams-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams.a /usr/local/lib/libboost_iostreams.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_iostreams.dylib /usr/local/lib/libboost_iostreams.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_locale-mt.a /usr/local/lib/libboost_locale-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_locale-mt.dylib /usr/local/lib/libboost_locale-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log-mt.a /usr/local/lib/libboost_log-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log-mt.dylib /usr/local/lib/libboost_log-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log.a /usr/local/lib/libboost_log.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log.dylib /usr/local/lib/libboost_log.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup-mt.a /usr/local/lib/libboost_log_setup-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup-mt.dylib /usr/local/lib/libboost_log_setup-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup.a /usr/local/lib/libboost_log_setup.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_log_setup.dylib /usr/local/lib/libboost_log_setup.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99-mt.a /usr/local/lib/libboost_math_c99-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99-mt.dylib /usr/local/lib/libboost_math_c99-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99.a /usr/local/lib/libboost_math_c99.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99.dylib /usr/local/lib/libboost_math_c99.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f-mt.a /usr/local/lib/libboost_math_c99f-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f-mt.dylib /usr/local/lib/libboost_math_c99f-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f.a /usr/local/lib/libboost_math_c99f.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99f.dylib /usr/local/lib/libboost_math_c99f.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l-mt.a /usr/local/lib/libboost_math_c99l-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l-mt.dylib /usr/local/lib/libboost_math_c99l-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l.a /usr/local/lib/libboost_math_c99l.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_c99l.dylib /usr/local/lib/libboost_math_c99l.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1-mt.a /usr/local/lib/libboost_math_tr1-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1-mt.dylib /usr/local/lib/libboost_math_tr1-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1.a /usr/local/lib/libboost_math_tr1.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1.dylib /usr/local/lib/libboost_math_tr1.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f-mt.a /usr/local/lib/libboost_math_tr1f-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f-mt.dylib /usr/local/lib/libboost_math_tr1f-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f.a /usr/local/lib/libboost_math_tr1f.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1f.dylib /usr/local/lib/libboost_math_tr1f.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l-mt.a /usr/local/lib/libboost_math_tr1l-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l-mt.dylib /usr/local/lib/libboost_math_tr1l-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l.a /usr/local/lib/libboost_math_tr1l.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_math_tr1l.dylib /usr/local/lib/libboost_math_tr1l.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor-mt.a /usr/local/lib/libboost_prg_exec_monitor-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor-mt.dylib /usr/local/lib/libboost_prg_exec_monitor-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor.a /usr/local/lib/libboost_prg_exec_monitor.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_prg_exec_monitor.dylib /usr/local/lib/libboost_prg_exec_monitor.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options-mt.a /usr/local/lib/libboost_program_options-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options-mt.dylib /usr/local/lib/libboost_program_options-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options.a /usr/local/lib/libboost_program_options.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_program_options.dylib /usr/local/lib/libboost_program_options.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random-mt.a /usr/local/lib/libboost_random-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random-mt.dylib /usr/local/lib/libboost_random-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random.a /usr/local/lib/libboost_random.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_random.dylib /usr/local/lib/libboost_random.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex-mt.a /usr/local/lib/libboost_regex-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex-mt.dylib /usr/local/lib/libboost_regex-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex.a /usr/local/lib/libboost_regex.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_regex.dylib /usr/local/lib/libboost_regex.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization-mt.a /usr/local/lib/libboost_serialization-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization-mt.dylib /usr/local/lib/libboost_serialization-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization.a /usr/local/lib/libboost_serialization.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_serialization.dylib /usr/local/lib/libboost_serialization.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals-mt.a /usr/local/lib/libboost_signals-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals-mt.dylib /usr/local/lib/libboost_signals-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals.a /usr/local/lib/libboost_signals.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_signals.dylib /usr/local/lib/libboost_signals.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line-mt.a /usr/local/lib/libboost_stacktrace_addr2line-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line-mt.dylib /usr/local/lib/libboost_stacktrace_addr2line-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line.a /usr/local/lib/libboost_stacktrace_addr2line.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_addr2line.dylib /usr/local/lib/libboost_stacktrace_addr2line.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic-mt.a /usr/local/lib/libboost_stacktrace_basic-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic-mt.dylib /usr/local/lib/libboost_stacktrace_basic-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic.a /usr/local/lib/libboost_stacktrace_basic.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_basic.dylib /usr/local/lib/libboost_stacktrace_basic.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop-mt.a /usr/local/lib/libboost_stacktrace_noop-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop-mt.dylib /usr/local/lib/libboost_stacktrace_noop-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop.a /usr/local/lib/libboost_stacktrace_noop.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_stacktrace_noop.dylib /usr/local/lib/libboost_stacktrace_noop.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system-mt.a /usr/local/lib/libboost_system-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system-mt.dylib /usr/local/lib/libboost_system-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system.a /usr/local/lib/libboost_system.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_system.dylib /usr/local/lib/libboost_system.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_test_exec_monitor-mt.a /usr/local/lib/libboost_test_exec_monitor-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_test_exec_monitor.a /usr/local/lib/libboost_test_exec_monitor.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_thread-mt.a /usr/local/lib/libboost_thread-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_thread-mt.dylib /usr/local/lib/libboost_thread-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer-mt.a /usr/local/lib/libboost_timer-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer-mt.dylib /usr/local/lib/libboost_timer-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer.a /usr/local/lib/libboost_timer.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_timer.dylib /usr/local/lib/libboost_timer.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure-mt.a /usr/local/lib/libboost_type_erasure-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure-mt.dylib /usr/local/lib/libboost_type_erasure-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure.a /usr/local/lib/libboost_type_erasure.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_type_erasure.dylib /usr/local/lib/libboost_type_erasure.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework-mt.a /usr/local/lib/libboost_unit_test_framework-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework-mt.dylib /usr/local/lib/libboost_unit_test_framework-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework.a /usr/local/lib/libboost_unit_test_framework.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_unit_test_framework.dylib /usr/local/lib/libboost_unit_test_framework.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wave-mt.a /usr/local/lib/libboost_wave-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wave-mt.dylib /usr/local/lib/libboost_wave-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization-mt.a /usr/local/lib/libboost_wserialization-mt.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization-mt.dylib /usr/local/lib/libboost_wserialization-mt.dylib
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization.a /usr/local/lib/libboost_wserialization.a
ln -f /usr/local/Cellar/boost/1.67.0_1/lib/libboost_wserialization.dylib /usr/local/lib/libboost_wserialization.dylib

无人在意的八哥

主题曲《像屎》

实习生黑锅
是很遥远的事情
八哥算什么
早无人在意
前埔不夜城
处处烤鱼
酒杯中好一片男男风情
最肯忘却故人失
最不屑一顾是相思
养着老怕人笑
还怕人看轻
新又来看乱码呆
竟不见有心人去改
庸才占着茅坑前途不在

百度分享不支持 HTTPS

百度分享不支持 HTTPS 的解决方案:https://github.com/hrwhisper/baiduShare,最早是 2016-07-09 发布,说明百度分享不支持 HTTPS 已经两年以上。

结论

百度可能听不进用户的话,用户宁愿自己解决问题……稣也亲自反馈过,应该是被无视了,至今还没官方支持!

Linux 内核代码风格翻译错误

Linux 内核代码风格 v4.19

分配一个零长数组的首选形式是这样的:
p = kcalloc(n, sizeof(...), ...);

原文是“The preferred form for allocating a zeroed array is the following:”,所以“零长”应该改为“填零”。

kcalloc 的文档也说:“kcalloc — allocate memory for an array. The memory is set to zero. ”

kcalloc 的定义 /include/linux/slab.h 更能说明:

1
2
3
4
5
6
7
8
9
10
/**
* kcalloc - allocate memory for an array. The memory is set to zero.
* @n: number of elements.
* @size: element size.
* @flags: the type of memory to allocate (see kmalloc).
*/
static inline void *kcalloc(size_t n, size_t size, gfp_t flags)
{
return kmalloc_array(n, size, flags | __GFP_ZERO);
}

“零长数组”应该是指:char u[0];

结论

疑智商太高,学习太快,中国的内核开发者都不屑看翻译的文档。