noblog 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/cmds/generate.js +7 -5
- package/dist/cmds/generate.js.map +1 -1
- package/dist/lib/nosm/default.js +0 -1
- package/dist/lib/nosm/default.js.map +1 -1
- package/dist/lib/nosm/nosm.js +1 -0
- package/dist/lib/nosm/nosm.js.map +1 -1
- package/output/00097769-2aac-4b6f-8f37-d9b658d46b2e +1 -1
- package/output/5bc1b19a-8350-48b3-aa19-8073561ad45b +1 -1
- package/output/c844b66d-0bf3-4f89-bbe1-5974f2de454b +9 -9
- package/output/sub/05009ca9-cb39-4356-8f24-c0db39cb4661 +2 -2
- package/output/sub/0b903359-2337-4ad9-adef-e77b69142581 +4 -4
- package/output/sub/232ae8ce-5ec3-4737-a18e-077774b84b1e +10 -10
- package/output/sub/44331753-a264-40a4-b86f-eafd676b3da0 +6 -6
- package/output/sub/4bac355b-24f0-49e7-a317-e4f1cad63c79 +1 -1
- package/output/sub/9a33b8cc-101a-4f6a-9852-115595cd166b +2 -2
- package/output/sub/9c060d29-39a2-432b-b06b-b0bd91989a52 +7 -7
- package/output/sub/b875bfe4-3c1e-4a8f-a56c-27a48ab874ca +3 -3
- package/output/sub/b8cbb8f9-f702-4a43-943c-02a6e39683d5 +2 -2
- package/output/sub/e339a686-bbb1-41d9-b6b5-18111e72a68c +2 -2
- package/output/sub/e859552b-c597-49ed-9ede-fab320fafd87 +1 -1
- package/package.json +1 -1
- package/src/cmds/generate.ts +4 -5
package/README.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This package aims to generate static content from notion.so and provide a plugable component/theme market for you bloggers.
|
|
4
4
|
|
|
5
|
-
the pattern would be like notablog, but more flexiable thanks to the mighty power of Astro
|
|
5
|
+
the pattern would be like notablog (see reference), but more flexiable thanks to the mighty power of Astro
|
|
6
6
|
|
|
7
7
|
# Usage
|
|
8
|
+
yet still experimental and not complete
|
|
9
|
+
|
|
8
10
|
```
|
|
9
|
-
npm install
|
|
11
|
+
npm install noblog
|
|
10
12
|
npx noblog .
|
|
11
13
|
```
|
|
12
14
|
|
package/dist/cmds/generate.js
CHANGED
|
@@ -27,18 +27,20 @@ async function main() {
|
|
|
27
27
|
try {
|
|
28
28
|
await Promise.all(futures);
|
|
29
29
|
for (const pageid of Object.keys(nob.MdCollection)) {
|
|
30
|
+
let fpath = sub_dir;
|
|
30
31
|
if (pages.find(page => page.id === pageid))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
fpath = save_dir;
|
|
33
|
+
const log = await nob.SaveJelly(pageid, fpath, nob.MdCollection[pageid]);
|
|
34
|
+
logger.info(log);
|
|
34
35
|
}
|
|
36
|
+
console.log(`success: finish dump all files to "${save_dir}"`);
|
|
35
37
|
}
|
|
36
38
|
catch (error) {
|
|
37
39
|
if (error instanceof Error) {
|
|
38
|
-
console.log(`
|
|
40
|
+
console.log(`failed: consider running with "v=true" - ${error.message}`);
|
|
39
41
|
}
|
|
40
42
|
else {
|
|
41
|
-
console.log('
|
|
43
|
+
console.log('failed: an unknown error occurred');
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cmds/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,IAAI,QAAQ,GAAG,oBAAoB,CAAA;AACnC,IAAI,OAAO,GAAG,KAAK,CAAA;AACnB,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAA;AACxB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAE9C,SAAS,IAAI;IACX,MAAM,KAAK,GAAG,0BAA0B,CAAC;IACzC,MAAM,OAAO,GAAG,sBAAsB,CAAC;IAEvC,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;IAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAEtC,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC/B,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACnD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC;gBACxC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/cmds/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtD,IAAI,QAAQ,GAAG,oBAAoB,CAAA;AACnC,IAAI,OAAO,GAAG,KAAK,CAAA;AACnB,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAA;AACxB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAE9C,SAAS,IAAI;IACX,MAAM,KAAK,GAAG,0BAA0B,CAAC;IACzC,MAAM,OAAO,GAAG,sBAAsB,CAAC;IAEvC,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;IAC7C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;IAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAEtC,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAC/B,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC3B,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACnD,IAAI,KAAK,GAAG,OAAO,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,MAAM,CAAC;gBACxC,KAAK,GAAG,QAAQ,CAAA;YAClB,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAA;YACxE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,sCAAsC,QAAQ,GAAG,CAAC,CAAA;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,4CAA4C,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAA"}
|
package/dist/lib/nosm/default.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../../src/lib/nosm/default.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../../src/lib/nosm/default.ts"],"names":[],"mappings":""}
|
package/dist/lib/nosm/nosm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nosm.js","sourceRoot":"","sources":["../../../src/lib/nosm/nosm.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"nosm.js","sourceRoot":"","sources":["../../../src/lib/nosm/nosm.ts"],"names":[],"mappings":"AAAA,uBAAuB"}
|
|
@@ -242,7 +242,7 @@ $写屏障=插入屏障+删除屏障$
|
|
|
242
242
|
可以理解到,如果`y`和`y`链路上的子对象没有被黑色对象引用,那么删除屏障实际上是活佛再世,抬了这些入土半截的对象一手,回收精度是偏低的。
|
|
243
243
|
|
|
244
244
|
|
|
245
|
-

|
|
246
246
|
|
|
247
247
|
|
|
248
248
|
那么混合写屏障呢?
|
|
@@ -41,7 +41,7 @@ To understand signal, we need to know its,
|
|
|
41
41
|
### **data structure**
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-

|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
Ok, if we don’t dive too deep, that’s it. An array of **bits**. If the bit is set, the according signal is received, otherwise not received. You can google the mapping between number and signal if you are interested.
|
|
@@ -129,25 +129,25 @@ $OM(2)$ step 1
|
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-

|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
$OM(1)$ step 1,这里进入第一层迭代,以第一个忠诚节点为例
|
|
136
136
|
|
|
137
137
|
|
|
138
|
-

|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
$OM(1)$ step 2
|
|
142
142
|
|
|
143
143
|
|
|
144
|
-

|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
$OM(1)$ step 3
|
|
148
148
|
|
|
149
149
|
|
|
150
|
-

|
|
151
151
|
|
|
152
152
|
|
|
153
153
|
以此类推还有五次 $OM(1)$ 需要完成,对于忠诚节点为 commander 的情况来说,都是一样的,这里再过一遍叛徒是 commander 的情况
|
|
@@ -156,31 +156,31 @@ $OM(1)$ step 3
|
|
|
156
156
|
$OM(1)$ step 1,这里进入第一层迭代,以叛徒为例,这里 $a,b,c,d,e$ 只是一个代数,它们可以等于任何一个决策。
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-

|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
$OM(1)$ step 2
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-

|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
$OM(1)$ step 3,就算有着叛徒,我们发现此时,所有节点的决策向量也是一样的。此时可能没有一个决策占了多数,所以我们姑且让没有达成一致时的默认决策为 $D$ 。
|
|
169
169
|
|
|
170
170
|
|
|
171
|
-

|
|
172
172
|
|
|
173
173
|
|
|
174
174
|
OK,回到主线,$OM(2)$ step2
|
|
175
175
|
|
|
176
176
|
|
|
177
|
-

|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
整理向量,得到最后的 $OM(2)$ step 3
|
|
181
181
|
|
|
182
182
|
|
|
183
|
-

|
|
184
184
|
|
|
185
185
|
|
|
186
186
|
可以朴素地认为,算法的核心就是为了使忠诚节点的最终结果一致。
|
|
@@ -51,13 +51,13 @@ For more information about this error, try `rustc --explain E0596`.
|
|
|
51
51
|
According to the hint from compiler, the key is trait `DerefMut`
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-

|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
Yyyyyyyyyyes, Arc only implements `Deref` rather than `DerefMut`[.](http://derefmut.so/) So only the method that called by `&self` can be adjusted. That’s why Mutex has to be wrapped outside the target value to complete the chain-style dereference: **`Arc`** `-Deref→` **`Mutex`** `-DerefMut→` **`value`**
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-

|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
|
|
@@ -46,7 +46,7 @@ Go 程序的执行由两层组成:Go Program,Runtime,即用户程序和运
|
|
|
46
46
|
一个展现了全景式的关系如下图:
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-

|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
## 为什么要 scheduler
|
|
@@ -91,7 +91,7 @@ Go scheduler 的目标:
|
|
|
91
91
|
> For scheduling goroutines onto kernel threads.
|
|
92
92
|
|
|
93
93
|
|
|
94
|
-

|
|
95
95
|
|
|
96
96
|
|
|
97
97
|
Go scheduler 的核心思想是:
|
|
@@ -115,7 +115,7 @@ Go scheduler 的核心思想是:
|
|
|
115
115
|
Go scheduler 会启动一个后台线程 sysmon,用来检测长时间(超过 10 ms)运行的 goroutine,将其调度到 global runqueues。这是一个全局的 runqueue,优先级比较低,以示惩罚。
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-

|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
# M:N model
|
|
@@ -149,7 +149,7 @@ go程序初始化时,会先
|
|
|
149
149
|
`newproc`用于创建运行`main func`的goroutine,循环调用`schedule`函数直到函数结束。
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-

|
|
153
153
|
|
|
154
154
|
|
|
155
155
|
# schedt
|
|
@@ -79,7 +79,7 @@ type waitq struct {
|
|
|
79
79
|
例如,创建一个容量为 6 的,元素为 int 型的 channel 数据结构如下 :
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-

|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
# 创建
|
|
@@ -171,7 +171,7 @@ func makechan(t *chantype, size int64) *hchan {
|
|
|
171
171
|
|
|
172
172
|
|
|
173
173
|
|
|
174
|
-

|
|
175
175
|
|
|
176
176
|
|
|
177
177
|
|
|
@@ -448,7 +448,7 @@ func main() {
|
|
|
448
448
|
|
|
449
449
|
|
|
450
450
|
|
|
451
|
-

|
|
452
452
|
|
|
453
453
|
|
|
454
454
|
|
|
@@ -460,7 +460,7 @@ func main() {
|
|
|
460
460
|
在程序的 17 行之前,chan 的整体数据结构如下:
|
|
461
461
|
|
|
462
462
|
|
|
463
|
-

|
|
464
464
|
|
|
465
465
|
|
|
466
466
|
`buf` 指向一个长度为 0 的数组,qcount 为 0,表示 channel 中没有元素。重点关注 `recvq` 和 `sendq`,它们是 waitq 结构体,而 waitq 实际上就是一个双向链表,链表的元素是 sudog,里面包含 `g` 字段,`g` 表示一个 goroutine,所以 sudog 可以看成一个 goroutine。recvq 存储那些尝试读取 channel 但被阻塞的 goroutine,sendq 则存储那些尝试写入 channel,但被阻塞的 goroutine。
|
|
@@ -472,13 +472,13 @@ func main() {
|
|
|
472
472
|
`recvq` 的数据结构如下:
|
|
473
473
|
|
|
474
474
|
|
|
475
|
-

|
|
476
476
|
|
|
477
477
|
|
|
478
478
|
再从整体上来看一下 chan 此时的状态:
|
|
479
479
|
|
|
480
480
|
|
|
481
|
-

|
|
482
482
|
|
|
483
483
|
|
|
484
484
|
G1 和 G2 被挂起了,状态是 `WAITING`。关于 goroutine 调度器这块不是今天的重点,当然后面肯定会写相关的文章。这里先简单说下,goroutine 是用户态的协程,由 Go runtime 进行管理,作为对比,内核线程由 OS 进行管理。Goroutine 更轻量,因此我们可以轻松创建数万 goroutine。
|
|
@@ -487,7 +487,7 @@ G1 和 G2 被挂起了,状态是 `WAITING`。关于 goroutine 调度器这块
|
|
|
487
487
|
一个内核线程可以管理多个 goroutine,当其中一个 goroutine 阻塞时,内核线程可以调度其他的 goroutine 来运行,内核线程本身不会阻塞。这就是通常我们说的 `M:N` 模型:
|
|
488
488
|
|
|
489
489
|
|
|
490
|
-

|
|
491
491
|
|
|
492
492
|
|
|
493
493
|
`M:N` 模型通常由三部分构成:M、P、G。M 是内核线程,负责运行 goroutine;P 是 context,保存 goroutine 运行所需要的上下文,它还维护了可运行(runnable)的 goroutine 列表;G 则是待运行的 goroutine。M 和 P 是 G 运行的基础。
|
|
@@ -499,13 +499,13 @@ G1 和 G2 被挂起了,状态是 `WAITING`。关于 goroutine 调度器这块
|
|
|
499
499
|
|
|
500
500
|
|
|
501
501
|
|
|
502
|
-

|
|
503
503
|
|
|
504
504
|
|
|
505
505
|
|
|
506
506
|
|
|
507
507
|
|
|
508
|
-

|
|
509
509
|
|
|
510
510
|
|
|
511
511
|
|
|
@@ -520,7 +520,7 @@ G1 和 G2 被挂起了,状态是 `WAITING`。关于 goroutine 调度器这块
|
|
|
520
520
|
G1 脱离与 M 的关系,但调度器可不会让 M 闲着,所以会接着调度另一个 goroutine 来运行:
|
|
521
521
|
|
|
522
522
|
|
|
523
|
-

|
|
524
524
|
|
|
525
525
|
|
|
526
526
|
G2 也是同样的遭遇。现在 G1 和 G2 都被挂起了,等待着一个 sender 往 channel 里发送数据,才能得到解救。
|
|
@@ -149,10 +149,10 @@ ANDQ $~15, SP
|
|
|
149
149
|
```
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-

|
|
153
153
|
|
|
154
154
|
|
|
155
|
-

|
|
156
156
|
|
|
157
157
|
|
|
158
158
|
上面两张图中,左侧用箭头标注了 16 字节对齐的位置。第一步表示向下移动 39 B,第二步表示与 `~15` 相与。
|
|
@@ -176,7 +176,7 @@ g0 栈的作用就是为运行 runtime 代码提供一个“环境”。
|
|
|
176
176
|
这里直接叠甲过,看初始化g0完以后是啥样子:
|
|
177
177
|
|
|
178
178
|
|
|
179
|
-

|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
stack.hi和stack.lo分别指向栈的高位和低位。
|
|
@@ -225,7 +225,7 @@ g0.m = &m0
|
|
|
225
225
|
于是,前面的图又增加了新的玩伴 m0:
|
|
226
226
|
|
|
227
227
|
|
|
228
|
-

|
|
229
229
|
|
|
230
230
|
|
|
231
231
|
## `schedinit`
|
|
@@ -312,7 +312,7 @@ atomicstorep(unsafe.Pointer(&allm), unsafe.Pointer(mp))
|
|
|
312
312
|
这一行将 allm 变成 m 的地址,这样变成了一个循环链表。之后再新建 m 的时候,新 m 的 alllink 就会指向本次的 m,最后 allm 又会指向新创建的 m。
|
|
313
313
|
|
|
314
314
|
|
|
315
|
-

|
|
316
316
|
|
|
317
317
|
|
|
318
318
|
上图中,1 将 m0 挂在 allm 上。之后,若新创建 m,则 m1 会和 m0 相连。
|
|
@@ -505,5 +505,5 @@ p0.m = m0
|
|
|
505
505
|
最后我们将 allp 和 allm 都添加到图上:
|
|
506
506
|
|
|
507
507
|
|
|
508
|
-

|
|
509
509
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
1. unsafe 包提供了 2 点重要的能力:
|
|
2
2
|
2. 任何类型的指针和 unsafe.Pointer 可以相互转换。uintptr 类型和 unsafe.Pointer 可以相互转换。
|
|
3
3
|
|
|
4
|
-

|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
pointer 不能直接进行数学运算,但可以把它转换成 uintptr,对 uintptr 类型进行数学运算,再转换成 pointer 类型。
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
> 💡 Replicated state machines are typically implemented using a replicated log
|
|
21
|
-
> 
|
|
22
22
|
>
|
|
23
23
|
> - Each server stores a log containing a series of commands, which its state machine executes in order
|
|
24
24
|
>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
> - State machines are deterministic, each computes the same state and the same sequence of outputs
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-

|
|
31
31
|
|
|
32
32
|
- Each server stores a log containing a series of commands, which its state machine executes in order
|
|
33
33
|
- Each log contains the same commands in the same order, so each state machine processes the same sequence of commands
|
|
@@ -97,7 +97,7 @@ type bmap struct {
|
|
|
97
97
|
`bmap` 就是我们常说的“桶”,桶里面会最多装 8 个 key,这些 key 之所以会落入同一个桶,是因为它们经过哈希计算后,哈希结果是“一类”的。在桶内,又会根据 key 计算出来的 hash 值的高 8 位来决定 key 到底落入桶内的哪个位置(一个桶内最多有8个位置)。
|
|
98
98
|
|
|
99
99
|
|
|
100
|
-

|
|
101
101
|
|
|
102
102
|
|
|
103
103
|
当 map 的 key 和 value 都不是指针,并且 size 都小于 128 字节的情况下,会把 bmap 标记为不含指针,这样可以避免 gc 时扫描整个 hmap。但是,我们看 bmap 其实有一个 overflow 的字段,是指针类型的,破坏了 bmap 不含指针的设想,这时会把 overflow 移动到 extra 字段来。
|
|
@@ -309,7 +309,7 @@ key 经过哈希计算后得到哈希值,共 64 个 bit
|
|
|
309
309
|
2. 再用哈希值的高 8 位,找到此 key 在 bucket 中的位置,这是在寻找已有的 key。最开始桶内还没有 key,新加入的 key 会找到第一个空位,放入。
|
|
310
310
|
3. buckets 编号就是桶编号,当两个不同的 key 落在同一个桶中,也就是发生了哈希冲突。冲突的解决手段是用链表法:在 bucket 中,从前往后找到第一个空位。这样,在查找某个 key 时,先找到对应的桶,再去遍历 bucket 中的 key。
|
|
311
311
|
|
|
312
|
-

|
|
313
313
|
|
|
314
314
|
|
|
315
315
|
上图中,假定 B = 5,所以 bucket 总数就是 $2^5 = 32$。首先计算出待查找 key 的哈希,使用低 5 位 `00110`,找到对应的 6 号 bucket,使用高 8 位 `10010111`,对应十进制 151,在 6 号 bucket 中寻找 topbits 值(HOB hash)为 151 的 key,找到了 2 号槽位,这样整个查找过程就结束了。
|
|
@@ -959,7 +959,7 @@ evacuate 函数的代码注释非常清晰,对着代码和注释是很容易
|
|
|
959
959
|
对于条件 1,就没这么简单了。要重新计算 key 的哈希,才能决定它到底落在哪个 bucket。例如,原来 B = 5,计算出 key 的哈希后,只用看它的低 5 位,就能决定它落在哪个 bucket。扩容后,B 变成了 6,因此需要多看一位,它的低 6 位决定 key 落在哪个 bucket。这称为 `rehash`。
|
|
960
960
|
|
|
961
961
|
|
|
962
|
-

|
|
963
963
|
|
|
964
964
|
|
|
965
965
|
因此,某个 key 在搬迁前后 bucket 序号可能和原来相等,也可能是相比原来加上 2^B(原来的 B 值),取决于 hash 值 第 6 bit 位是 0 还是 1。
|
|
@@ -971,7 +971,7 @@ evacuate 函数的代码注释非常清晰,对着代码和注释是很容易
|
|
|
971
971
|
例如,原始 B = 2,1号 bucket 中有 2 个 key 的哈希值低 3 位分别为:010,110。由于原来 B = 2,所以低 2 位 `10` 决定它们落在 2 号桶,现在 B 变成 3,所以 `010`、`110` 分别落入 2、6 号桶。
|
|
972
972
|
|
|
973
973
|
|
|
974
|
-

|
|
975
975
|
|
|
976
976
|
|
|
977
977
|
理解了这个,后面讲 map 迭代的时候会用到。
|
|
@@ -1026,7 +1026,7 @@ useX = hash&newbit == 0
|
|
|
1026
1026
|
下面通过图来宏观地看一下扩容前后的变化。
|
|
1027
1027
|
|
|
1028
1028
|
|
|
1029
|
-

|
|
1030
1030
|
|
|
1031
1031
|
|
|
1032
1032
|
扩容前,B = 2,共有 4 个 buckets,lowbits 表示 hash 值的低位。假设我们不关注其他 buckets 情况,专注在 2 号 bucket。并且假设 overflow 太多,触发了等量扩容(对应于前面的条件 2)。
|
|
@@ -1035,13 +1035,13 @@ useX = hash&newbit == 0
|
|
|
1035
1035
|
扩容完成后,overflow bucket 消失了,key 都集中到了一个 bucket,更为紧凑了,提高了查找的效率。
|
|
1036
1036
|
|
|
1037
1037
|
|
|
1038
|
-

|
|
1039
1039
|
|
|
1040
1040
|
|
|
1041
1041
|
假设触发了 2 倍的扩容,那么扩容完成后,老 buckets 中的 key 分裂到了 2 个 新的 bucket。一个在 x part,一个在 y 的 part。依据是 hash 的 lowbits。新 map 中 `0-3` 称为 x part,`4-7` 称为 y part。
|
|
1042
1042
|
|
|
1043
1043
|
|
|
1044
|
-

|
|
1045
1045
|
|
|
1046
1046
|
|
|
1047
1047
|
注意,上面的两张图忽略了其他 buckets 的搬迁情况,表示所有的 bucket 都搬迁完毕后的情形。实际上,我们知道,搬迁是一个“渐进”的过程,并不会一下子就全部搬迁完毕。所以在搬迁过程中,oldbuckets 指针还会指向原来老的 []bmap,并且已经搬迁完毕的 key 的 tophash 值会是一个状态值,表示 key 的搬迁去向。
|
|
@@ -174,7 +174,7 @@ G的状态有以下9种,可以参见[代码](https://github.com/golang/go/blob
|
|
|
174
174
|
G的状态流转:
|
|
175
175
|
|
|
176
176
|
|
|
177
|
-

|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
### M的结构
|
|
@@ -203,7 +203,7 @@ type m struct {
|
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
|
|
206
|
-

|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
### P的内部结构
|
|
@@ -272,7 +272,7 @@ P有以下几种状态,参加[源码](https://github.com/golang/go/blob/562212
|
|
|
272
272
|
P的状态流转:
|
|
273
273
|
|
|
274
274
|
|
|
275
|
-

|
|
276
276
|
|
|
277
277
|
|
|
278
278
|
### 调度器的内部结构
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
# Overview
|
|
@@ -191,7 +191,7 @@ go build -x -work main.go 1> transcript.txt 2>&1
|
|
|
191
191
|
最后用一张图来总结 go bootstrap 过程吧:
|
|
192
192
|
|
|
193
193
|
|
|
194
|
-

|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
`main` 函数里执行的一些重要的操作包括:新建一个线程执行 `sysmon` 函数,定期垃圾回收和调度抢占;启动 `gc`;执行所有的 `init` 函数等等。
|
|
@@ -156,7 +156,7 @@ type interfacetype struct {
|
|
|
156
156
|
这里通过一张图来看下 `iface` 结构体的全貌:
|
|
157
157
|
|
|
158
158
|
|
|
159
|
-

|
|
160
160
|
|
|
161
161
|
|
|
162
162
|
## eface (empty interface)
|
|
@@ -176,7 +176,7 @@ type eface struct {
|
|
|
176
176
|
相比 `iface`,`eface` 就比较简单了。只维护了一个 `_type` 字段,表示空接口所承载的具体的实体类型。`data` 描述了具体的值。
|
|
177
177
|
|
|
178
178
|
|
|
179
|
-

|
|
180
180
|
|
|
181
181
|
|
|
182
182
|
我们来看个例子:
|
|
@@ -19,7 +19,7 @@ Sending and receiving RequestVote RPCs
|
|
|
19
19
|
</details>
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-

|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
Step**s:**
|
package/package.json
CHANGED
package/src/cmds/generate.ts
CHANGED
|
@@ -4,7 +4,6 @@ import { Logger } from "tslog";
|
|
|
4
4
|
import { Noblog } from "../lib/nomd/nomd.js";
|
|
5
5
|
import { GetAllPosts } from "../lib/notion/client.js";
|
|
6
6
|
|
|
7
|
-
let v: boolean = false;
|
|
8
7
|
let save_dir = "./content/markdown"
|
|
9
8
|
let sub_dir = "sub"
|
|
10
9
|
const nob = new Noblog()
|
|
@@ -35,11 +34,11 @@ async function main() {
|
|
|
35
34
|
try {
|
|
36
35
|
await Promise.all(futures);
|
|
37
36
|
for (const pageid of Object.keys(nob.MdCollection)) {
|
|
38
|
-
let fpath =
|
|
39
|
-
if (pages.find(page => page.id
|
|
40
|
-
fpath =
|
|
37
|
+
let fpath = sub_dir;
|
|
38
|
+
if (pages.find(page => page.id === pageid))
|
|
39
|
+
fpath = save_dir
|
|
41
40
|
const log = await nob.SaveJelly(pageid, fpath, nob.MdCollection[pageid])
|
|
42
|
-
|
|
41
|
+
logger.info(log);
|
|
43
42
|
}
|
|
44
43
|
console.log(`success: finish dump all files to "${save_dir}"`)
|
|
45
44
|
} catch (error) {
|