纯数字 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

为编译 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];

结论

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

截屏热键怎么设置才能截菜单?

稣习惯使用 Ctrl+Shift+A 或 Ctrl+F12 作为截屏热键,而微信 PC 版的默认截屏热键是 Alt+A。

今天被人问“怎么截菜单?”稣一脸懵逼,回答:“和截其它,有什么不同吗?”对方说:“一按截屏热键菜单就退出了!”

稣恍然大悟,原来 TA 没改默认热键,只要按下 Alt,菜单确实会退出……

默认的不一定最好。PS:TX 程序员不懂这个道理吗?为什么选择 Alt+A 这样奇葩的组合!

显卡名称包含汉字导致 DX11 程序无法正常工作

某游戏在 RemoteFX 远程桌面下无法正常运行。提示:

运行引擎需要DX11特征等级10.0

英文版提示:

DX11 feature level 10.0 is required to run the engine.

稣立刻调用 dxdiag 查看,结果 Feature Level 10.0 是支持的!

然后决定自己写个 DX11 程序测试一下,于是找到这里例子:Tutorial 3: Initializing DirectX 11,稍加修改后运行,得到一个错误提示:

MessageBox(hwnd, L”Could not initialize Direct3D.”, L”Error”, MB_OK);

接下来,仔细检查这个初始化过程,发现居然是因为 wcstombs_s 失败引起的:

1
2
// Convert the name of the video card to a character array and store it.
error = wcstombs_s(&stringLength, m_videoCardDescription, 128, adapterDesc.Description, 128);

原来是因为 RemoteFX 显卡的名字里有汉字……

RemoteFX 3D 视频适配器

设备名称:

Microsoft RemoteFX 图形设备 - WDDM

通过注册表改显卡名字,测试代码的问题解决!但 wcstombs_s 这块代码其实并无与显卡功能相关,去掉这段代码也可以解决问题。

留一法交叉验证

题目

假设有如下一组输入并输出一个实数的数据,则线性回归(Y = bX + c)的留一法交叉验证均方差为?

X Y
0 2
2 2
3 1

A. 10/27
B. 20/27
C. 50/27
D. 49/27

学习

交叉验证(Cross Validation)

也称作循环估计(Rotation Estimation),是一种统计学上将数据样本切割成较小子集的实用方法。

在模式识别(Pattern Recognition)和机器学习(Machine Learning)的相关研究中,经常会将整个数据集合分成两个部分,分别是训练集合和测试集合。在一个 n 个元素的集合,选择 r 个元素做训练集(非空集,r > 0),剩下的 n - r 个做测试集,这可以用“组合”计算有多少种可能。把每种组合都做过一遍就是交叉验证。

组合(Combination)

nCr 表示由 n 个不同元素中,每次取出 r 个不重复之元素的组合,用符号 C n(下标)r(上标)表示。

留一法交叉验证(Leave-one-out Cross Validation)

只留一个元素做测试集,即:r = n - 1。

均方差

标准差(Standard Deviation),别名:标准偏差、实验标准差、均方差,是离均差平方的算术平均数的平方根,用 σ 表示。标准差是方差的算术平方根。标准差能反映一个数据集的离散程度。平均数相同的两组数据,标准差未必相同。

解题

三个元素的集合留一,一共有 3C1 = 3 种组合,画 3 个点:

  • A = (0, 2)
  • B = (2, 2)
  • C = (3, 1)
  1. 连接 A 和 B,得到直线 Y = 2,C 点的偏差 = 2 - 1 = 1
  2. 连接 A 和 C,得到直线 Y = (6 - X) / 3,B 点的偏差 = 4/3 - 2 = -2/3
  3. 连接 B 和 C,得到直线 Y = 4 - X,A 点的偏差 = 4 - 2 = 2

所以方差为:(1^2 + (2/3)^2 + 2^2) / 3 = (9 + 4 + 4 * 9) / 27 = 49/27

题目说的是“均方差”,根据百度百科标准差词条的说法,“均方差”==标准差,要开平方……所以题目中的答案没有一个是对的。出题者想让我们选 D,稣偏要选 F,你懂的 ck……

小本科对非欧几里得几何学脱敏的故事

高中时代

从小喜欢天文和数学,但高中时,有两个事件,促使后来读了挨踢专业。

  1. 穷。所有人都说读天文学很烧钱,穷人家是负担不起的,没学到家就出来又不好就业。

    高一,有电脑课,但觉得电脑没人脑聪明,没什么兴趣。后来意外看到 Bill Gates 的事迹,明白了挨踢行业是很赚钱的,而且这个行业不怎么需要讲人情世故,也是自己可能擅长的领域。

  2. 被非欧几何打击了。和数学课代表交好,经常讨论数学,都喜欢自学超前的知识。其中讨论过的一个最大的未解之谜就是:

    三角形内角和可以大于或小于 180 度。

    当时只学到一些皮毛概念,仅知道“黎曼几何学是大于,罗巴切夫斯基几何学是小于”,但已经大受打击……

大学时代

大部分时间都用于实践编程技术,原来比较擅长的数学和英语都被牺牲,不怎么认真去学。

但有追究过非欧几何学到底怎么来的:公理体系中采用了不同的平行定理。

  • 在平面内,从直线外一点,至少可以做两条直线和这条直线平行;

  • 在平面内,从直线外一点,有且只有一条直线和这条直线平行;

  • 在平面内,从直线外一点,不能做直线和已知直线平行。

当时没有去深入理解,看了一个例子说球体表面的两条直线都会相交,结果就对非欧几何过敏了……脑子里不断产生抵抗,球面不是平的,球面的直线特么是弯的,这让直男怎么接受?

然后就把非欧几何学当成是外星的哲学了,觉得不是个有用的理论,完全忽视了自以为能理解的广义相对论是和黎曼几何学有关的!

突然脱敏

最近补了点数学基础,顺便想把这个问题解决掉。纠正过程如下:

  • 球面上的两点之间,直线最短,嗯,在球体上看,最短的直线是穿过球体内部的,那个才是直的。

    不对,我们讨论的是二维的面,你怎么扯到三维的球体,还内部?

  • 球面上的直线是指什么?用地球来比方,赤道线和纬度线是不是都算?

    赤道线是,但其他的纬度线不是,其它纬度线上的两点之间最短的线,并不在纬度线上,纬度线绕的更远,最短的还是这两点加上球心切面上两点之间那段圆弧(劣弧)。

  • 直线只是定义一样,但在两种不同体系的面上样子是不一样的?

    是的,“两点之间,直线段最短”球面上的直线,在三维世界看确实是弯的,但在二维世界,它是直的……是直的……是直的。在四维空间看我们的世界,也许也是弯的,但反正我们在三维空间看,是直的!虽然我们能找到其实是弯的证据。

脱敏是很重要的能力

这其实不难理解,但长期自我抑制,不去解决它,再好的理解能力也没用武之地。

有些故事,要先相信,才有续集。

你是直的,还是弯的?

卸载 LSP 并重启系统依然有服务加载它

发现问题,2012-12-11 18:16:00

  快游(网游加速器)包含一个 LSP,属于加速核心组件,在测试 LSP 期间,发现一个奇怪的现象:反注册它,并 netsh winsock reset 加重启好几次……依然有程序加载它。用 Process Explorer 查看是:IpOverUsbSvc.exe 和 daemonu.exe。把 LSP 的 DLL 文件删掉,再重启,可以消灭这个奇怪的现象。但后来想重现这个怪现象时,却无法重现。

重现和解决问题,2012-12-25 15:38:00

  问题自然重现,继续研究。这两个进程对应的服务名是:IpOverUsbSvc 和 nvUpdatusService。手动重启这两个服务后,即不再加载 LSP。推理:这两个服务很可能每次重启机器时都没有正常关闭,系统提供了某种机制让他们在下一次重启后快速恢复了运行现场(保留了有 LSP 注册时的环境)。

分析问题,2013-03-26 23:24:30

  时隔三个月,偶然看到介绍”混合式关机”的文章,恍然大悟,原来是这货引发的八哥!

在安装 Win8 后,很多人都体验到了其开关机惊人的速度,尤其是开机速度,相比 Win7 之下,它提升的不止是一点半点。在某些超极本和配备了 SSD 的机器上,其开关机速度可以在数秒以内。例如 Surface Pro,其实测系统引导速度为2秒,从启动到自动登录到开始屏幕只要6秒。

究竟是什么技术提升了 Win8 的开关机速度呢?如果要用最简单的一句话概括,那应该是”系统会话休眠”,或者更简单的,”混合式关机”。

在 以往的 Windows OS 中,典型的关机顺序为:

  1. 单击”关机”。

  2. Windows 广播运行应用程序关机信息,让应用程序可以保存数据和设置。应用程序也可以要求一些额外的时间以结束其当前工作。

  3. Windows 为每个登录用户关闭用户会话。

  4. Windows 向服务发送关机信息,通知已开始关机,接着关闭服务。如果服务未响应,系统将强制关闭。

  5. Windows 向设备广播信息,示意设备进行关闭。

  6. Windows 关闭系统会话(也称为”会话 0”)。

  7. Windows 刷新系统驱动器待决数据,以确保完全保存。

  8. Windows 通过 ACPI 界面向系统发送信号以给计算机断电。

看着以上的典型关机步骤,你是不是也有想到一些步骤对应的屏幕上的 UI 表现呢~

再来看看 Windows 8 采用的混合式关机主要步骤:

  1. 单击”关机”。

  2. Windows 广播运行应用程序关机信息,让应用程序可以保存数据和设置。应用程序也可以要求取得一些额外的时间以结束其当前工作。

  3. Windows 为每个登录用户关闭用户会话。

  4. 系统会话休眠,并掉电。

可见,Windows 8 只关闭用户会话而不像以前那样完全关闭计算机。此时, Windows 不再等待并结束系统服务和关闭会话 0,而是让其进入休眠。这种关闭用户会话+休眠系统服务和系统会话的做法,被称为”混合式关机”,也就不难理解了。

或者说得通俗点,就好比你之前打扫卫生时,需要先组装专业的拖布,组装好了以后,才能开始打扫卫生。而现在,你可以拿起拖布直接开始打扫,因为你上次打扫完之后,并没有将拖布这一工具像以往那样拆卸下来收好。

开机在结构上是关机的逆过程,所以有了混合式关机,开机自然也就快了。但是,除了 RAID 卡外,一般硬盘的读取速度会比写入速度略快,加上关机的时候,系统会通知并等待应用程序退出,所以从感官上,开机过程会比关机过程显得要快一些。