Changkun's Blog欧长坤的博客

Science and art, life in between.科学与艺术,生活在其间。

  • Home首页
  • Ideas想法
  • Posts文章
  • Tags标签
  • Bio关于
Changkun Ou

Changkun Ou

Human-AI interaction researcher, engineer, and writer.人机交互研究者、工程师、写作者。

Bridging HCI, AI, and systems programming. Building intelligent human-in-the-loop optimization systems. Informed by psychology, sociology, cognitive science, and philosophy.连接人机交互、AI 与系统编程。构建智能的人在环优化系统。融合心理学、社会学、认知科学与哲学。

Science and art, life in between.科学与艺术,生活在其间。

276 Blogs博客
165 Tags标签
Changkun's Blog欧长坤的博客
idea想法 2021-02-10 00:00:00

A New GC Pacer全新的 GC 调步器

Today, the Go team released a brand new GC pacer design. Let’s briefly discuss what problems existed in the previous design and what the new design aims to solve.

The current Go runtime GC is a concurrent mark-sweep collector, which involves two core problems that need to be solved: 1) when to start GC and how many workers to launch for collection, to prevent the collector from using too many computing resources and affecting efficient execution of user code; 2) how to prevent the garbage collection speed from being slower than the memory allocation speed.

To address these problems, as early as Go 1.5, the Go team treated this as an optimization problem of minimizing heap growth rate and CPU usage, which led to two key components: 1) the pacer: predicting GC trigger timing based on heap growth speed; 2) mark assist: pausing user code that allocates too fast, redirecting goroutines that are allocating memory to perform garbage marking work, in order to smoothly complete the current GC cycle.

However, when making pacing decisions, this GC contains a hidden assumption: the allocation rate is always a constant (1+GOGC/100). Unfortunately, due to the existence of mark assist and discrepancies between implementation and the theoretical model, this assumption is actually incorrect. This leads to several hard-to-solve problems: 1) when the allocation rate violates the constant assumption, the predicted start time is too late, requiring excessive CPU consumption — while GOGC can be dynamically adjusted, it remains a hyperparameter requiring extensive domain experience to tune manually; 2) since the optimization targets heap growth without heap memory size limits, either setting GOGC too large or encountering peak allocations causes rapid heap growth leading to OOM; 3) newly allocated memory within the current GC cycle is left to the next GC cycle for collection, and mark assist’s allocation throttling causes latency pauses (STW); 4) …

So what has the new pacer redesigned to solve these problems?

As mentioned above, the main source of various problems is the incorrect assumption that the allocation rate is a constant. So naturally, it’s easy to think of using the mark assist component to dynamically calculate the allocation rate during modeling, thereby achieving the goal of dynamically adjusting the heap target. Unfortunately, the original design only tracked allocations on the heap, without considering the stack or global variables. To make the problem more comprehensive, the new design introduces an “assist ratio” — the ratio of allocations produced but not collected in the current GC cycle (A) to the amount of scanning completed in the current GC cycle (B), i.e., A/B. This metric more intuitively reflects the actual difficulty of GC work: if the user allocation rate is too high, A increases, the assist ratio rises, and more assistance is needed from the mark assist; if the allocation rate is moderate, the assist ratio decreases. With the introduction of the assist ratio, the pacer can dynamically adjust the assist work, thereby resolving the pauses caused by the assist.

Let’s look at a practical scenario: when a sudden burst of peak requests arrives, the number of goroutines increases dramatically, generating a large number of stacks and allocation tasks. Here are the simulation results: Figure 1 shows the pacer before adjustment, Figure 2 shows the pacer after adjustment. As shown in the lower-left of Figure 1, the heap target workload is consistently underestimated, causing the heap to always overshoot; while the new pacer can quickly converge to zero and complete the heap target prediction. The upper-right of Figure 1 shows that the actual GC CPU usage is always lower than the target usage, failing to meet the expected metrics; while the newly designed pacer can quickly converge to the target CPU usage.

Of course, due to space constraints, the above is only a very brief introduction to the new pacer design. If you are interested in this topic, you can refer to the following links. There will be opportunities to share more detailed analysis in the future.

  1. Existing problems with the GC pacer: https://golang.org/issue/42430
  2. Design document for the new pacer: https://go.googlesource.com/proposal/+/a216b56e743c5b6b300b3ef1673ee62684b5b63b/design/44167-gc-pacer-redesign.md
  3. Related proposal: https://golang.org/issue/44167
  4. Simulator for the new GC pacer model: https://github.com/mknyszek/pacer-model

今天,Go 团队发布了一个全新的 GC 的调步器(Pacer)设计。这次就来简单聊一聊这个以前的设计有什么问题,新的设计又旨在解决什么问题。

目前 Go 运行时的 GC 是一个并发标记清理的回收器,这涉及两个需要解决的核心问题:1)何时启动 GC 并启动多少数量的 worker 进行搜集从而防止回收器使用过多的计算资源影响用户代码的高效执行;2)如何防止收集垃圾的速度慢于内存分配的速度。

为解决这些问题,早在 1.5,Go 团队将这个问题视作一个最小化堆的增长速率和 CPU 的使用率的优化问题,从而促成了两个关键组件:1)调步器:根据堆的增长速度来预测 GC 的触发时机;2)标记助理 (Mark Assist):暂停分配速度过快的用户代码,将正在分配内存的用户代码转去执行垃圾标记的工作,以便顺利完成当前的 GC 周期。

然而这样的 GC 在实施调步决策时,包含一个隐藏的假设:分配速率总是一个常数(1+GOGC/100),可惜由于标记助理的存在、实现与理论模型的差异,导致这个假设其实并不正确。进而带来的很难解决的问题:1)当分配速率违反常数假设时,预测的启动时间太晚反而需要消耗过多的 CPU,虽然可以动态的调整 GOGC,但这仍然是一个超参数,人工优化需要大量的领域经验,很难直观的使用这个变量对 GC 进行优化;2)由于优化问题是以堆的增长为目标,由于没有堆内存大小的使用限制,无论是设置过大的 GOGC 或者出现峰值分配时都会导致堆的迅速增长从而 OOM;3)在当前 GC 周期内新分配的内存将留到下一个 GC 周期进行回收,标记助理暂缓分配带来的延迟停顿 STW;4)… 那么新的调步器为解决这些问题做了什么重新设计呢?

正如前面所说,产生各类问题的主要来源是对分配速率为常数这一错误的假设,那么自然也就很容易想到在建模的过程:利用标记助理这一组件来动态的计算分配的速率,从而达到动态调整堆目标的目的。可惜的是原来的设计中标记助理仅统计了堆上的分配情况,而对栈或全局变量没有加以考虑。为了让问题考虑得更加全面,新设计中引入了一个「辅助率」,表示当前 GC 周期新产生但没有回收的分配量(A)与当前 GC 周期完成的扫描量(B)之比,A/B。这一指标更加直观的反应了 GC 的实际工作难度:如果用户分配速率过高,那么 A 将增大,进而辅助率增高,需要助理提供更多的辅助;如果分配速率适中,辅助率下降。根据辅助率的引入,调步器便可动态的的调整助理的辅助工作,进而解决辅助时带来的停顿。

我们来看一个实际的场景:当突然出现大量峰值请求时,goroutine数量大量增加,从而产生大量栈和分配任务,极其模拟的结果:图 1 是调整前的调步器,图 2 是调整后的调步器。可见图1左下角显示,总是错误的低估了堆目标工作量,导致堆总是在过冲;而新的调步器能很快的收敛到零,完成堆目标的预测;图 1 右上角则表明实际的 GC CPU 使用率总是比目标使用率低,从而为能完成预期指标;而新设计的调步器则能很快收敛到目标的 CPU 使用率。

当然,限于篇幅上面只是对新的调步器设计做了一个非常简略的介绍。如果对这个内容感兴趣,可以查阅后面的这些链接,之后有机会再对此设计做进一步详细的分享。

  1. GC 调步器现存的问题:https://golang.org/issue/42430
  2. 新调步器的设计文档:https://go.googlesource.com/proposal/+/a216b56e743c5b6b300b3ef1673ee62684b5b63b/design/44167-gc-pacer-redesign.md
  3. 相关的提案:https://golang.org/issue/44167
  4. GC 新调步器模型的模拟器:https://github.com/mknyszek/pacer-model
idea想法 2021-01-27 00:00:00

Go 1.16 Big ChangesGo 1.16 的重大变化

Go 1.16 has released many very interesting changes. Here is a brief summary:

russ cos: deprecated.

  • https://twitter.com/_rsc/status/1351676094664110082
  • https://go-review.googlesource.com/c/go/+/285378
  • https://github.com/golang/go/issues/43724
  1. Support for darwin/arm64
    1. Issues encountered supporting darwin/arm64
      • Apple’s bug: related to signal preemption
    2. Apple Silicon M1 performance
      • But crypto performance is poor
      • Release cycle: https://github.com/golang/go/wiki/Go-Release-Cycle
    3. Compiler bootstrapping process
  • Installing Go: https://gist.github.com/Dids/dbe6356377e2a0b0dc8eacb0101dc3a7

  • https://github.com/golang/go/issues/42684

    • Kernel Panic Episode 62: Your Computer Isn’t Yours, Code Signing, OCSP Server
    • Ken Thompson Turing Award lecture: Reflections on Trusting Trust
      • TODO
    • Apple’s long-standing code signing issues; I encountered similar problems doing Electron in the early days, and these issues still exist today
  • Asynchronous preemption random crashes, a Rosetta bug: https://github.com/golang/go/issues/42700

  • Bootstrapping, installation confusion: https://github.com/golang/go/issues/38485#issuecomment-735360572

    • Go’s bootstrapping consists of three steps
        1. 1.4 C version TODO
        1. tool chain 1
        1. tool chain 2
        1. tool chain 3
  • Run x86 programs under Rosetta: arch --x86_64

  • M1 compatibility status in dotfiles: https://github.com/changkun/dotfiles/issues/2

    • https://doesitarm.com/
    • https://isapplesiliconready.com/
  • Got it in early December, have been using it for almost two months now — very smooth, battery life is incredible

  • My essential third-party software list:

    • homebrew (compatibility is not great, but fortunately most dependent software is written in Go, and Go’s support is very complete)
      • Breaks compatibility casually, removes software distribution — there was a tool called rmtrash that I had been using since around 2014, but it was removed from distribution last year, so I wrote a fully compatible tool changkun.de/s/rmtrash, but it wasn’t merged; they said it needed to be approved by the original author to bypass popularity restrictions, but the original author is unreachable
    • vscode (have been using Insider long-term)
    • macvim
    • tmux
    • oh-my-zsh
    • Blender (Cycles ray tracing doesn’t support GPU, but editing meshes with less than a million vertices is fine)
    • iTerm: supports M1
    • Chrome: supports M1
    • MacTex: supports M1
    • Docker: released support a week before Christmas, works perfectly, no issues so far
  1. Go Modules changes

    1. Collecting feedback
    2. Complex dependency management — what’s the most complex project dependency you’ve managed in practice, how many modules, and what do you write for each dependency upgrade? What did you use before Go modules?
      1. My experience: Go vendor, 1.10 dep, 1.11 go modules
      2. GOPATH project management — although GOPATH has been removed, I still follow the GOPATH convention
    3. Minimum version selection
      1. Semantic Versioning: major.minor.patch
      2. The classic diamond dependency problem: A depends on B and C, B and C each depend on different versions of D that are incompatible, so no specific version of D can be selected — semantic import versioning eliminates this by adding the major version number requirement at the end of the import path /v2
      3. dep doesn’t allow diamond dependencies, upgrades are very difficult
      4. Build reproducibility — without a lock file, >= dependencies change over time
      5. Select the minimum usable version — builds don’t change over time
      6. https://www.youtube.com/watch?v=F8nrpe0XWRg&ab_channel=SingaporeGophers
      7. Misunderstood working methods
      8. GOPATH
      9. vendor
      10. Three key points
      11. Compatibility
      12. Reproducibility
      13. Cooperation (often overlooked by many)
    4. Go Modules enabled by default, go build must include go.mod file, otherwise compilation fails
    5. build/test will not upgrade modules
    6. Default -mod=vendor
  2. File system interface

    1. Why is the fs.FS abstraction important

      1. Unix file system abstract always disk blocks
      2. Network file systems (Upspin) abstract away machines
      3. REST abstracts nearly anything
      4. cp doesn’t care whether it’s moving file blocks, or even where the file is — it could be different disks or different machines
      5. Defines the “generics” for any file type tools
    2. What major changes it caused

      1. io/ioutil
        1. Russ Cox’s explanation of deprecated in Go (https://twitter.com/_rsc/status/1351676094664110082)
        2. https://www.srcbeat.com/2021/01/golang-ioutil-deprecated/
      2. Other fs abstractions
      3. Rob Pike’s 2016/2017 Gopherfest, Upspin, Changkun’s Midgard
        1. https://www.youtube.com/watch?v=ENLWEfi0Tkg&ab_channel=TheGoProgrammingLanguage
        2. FUSE: filesystem in userspace
        3. https://changkun.de/s/midgard
        4. Every user has a private root, no global root, r@golang.org/some/stuff, user names look like email addresses
        5. Access control defined by plain text files read: r@golang.org, ann@example.com
      4. Currently a very simple implementation, just a read-only file system
      5. ReadDir and DirEntry
        1. https://benhoyt.com/writings/go-readdir/
      6. Extensible directions: memoryFS, support for writing back to disk, hashFS for CDN support
      7. Remaining issues… e.g. 44166
      1
      2
      3
      4
      5
      6
      7
      
      import _ "embed"
      //go:embed a.txt
      var s string
      
      import "embed"
      type embed.String string
      var s embed.String
      
      1
      
      
      
  3. File embedding //go:embed

    1. Basic functionality of the new feature
    2. Some possible applications
    3. Some features discussed during the feature freeze cycle
    4. https://blog.carlmjohnson.net/post/2021/how-to-use-go-embed/
  4. Runtime memory management

    1. Return to MADV_DONTNEED
    • https://blog.changkun.de/posts/pss-uss-rss/
    1. New monitoring infrastructure runtime/metrics
    • Previous monitoring functions: runtime.ReadMemStats, debug.GCStats
    • runtime/metrics:
      • metrics.All()
      • Issue 37112
 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
package main

import (
	"fmt"
	"runtime/metrics"
)

func main() {
	// Get descriptions for all supported metrics.
	descs := metrics.All()

	// Create a sample for each metric.
	samples := make([]metrics.Sample, len(descs))
	for i := range samples {
		samples[i].Name = descs[i].Name
	}

	// Sample the metrics. Re-use the samples slice if you can!
	metrics.Read(samples)

	// Iterate over all results.
	for _, sample := range samples {
		// Pull out the name and value.
		name, value := sample.Name, sample.Value

		// Handle each sample.
		switch value.Kind() {
		case metrics.KindUint64:
			fmt.Printf("%s: %d\n", name, value.Uint64())
		case metrics.KindFloat64:
			fmt.Printf("%s: %f\n", name, value.Float64())
		case metrics.KindFloat64Histogram:
			// The histogram may be quite large, so let's just pull out
			// a crude estimate for the median for the sake of this example.
			fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram()))
		case metrics.KindBad:
			// This should never happen because all metrics are supported
			// by construction.
			panic("bug in runtime/metrics package!")
		default:
			// This may happen as new metrics get added.
			//
			// The safest thing to do here is to simply log it somewhere
			// as something to look into, but ignore it for now.
			// In the worst case, you might temporarily miss out on a new metric.
			fmt.Printf("%s: unexpected metric Kind: %v\n", name, value.Kind())
		}
	}
}

func medianBucket(h *metrics.Float64Histogram) float64 {
	total := uint64(0)
	for _, count := range h.Counts {
		total += count
	}
	thresh := total / 2
	total = 0
	for i, count := range h.Counts {
		total += count
		if total > thresh {
			return h.Buckets[i]
		}
	}
	panic("should not happen")
}
  1. Other noteworthy features
    1. os/signal.NotifyContext
    2. Memory model fixes
    3. Linker optimizations

Go 1.16 发布了非常多非常有趣的变,尝试做一个简单的总结:

russ cos: deprecated.

  • https://twitter.com/_rsc/status/1351676094664110082
  • https://go-review.googlesource.com/c/go/+/285378
  • https://github.com/golang/go/issues/43724
  1. 支持 darwin/arm64
    1. 支持 darwin/arm64 上遇到的问题
      • 苹果的bug: 与信号抢占有关
    2. Apple Silicon M1 性能
      • 但是在加密上性能很差
      • 发版周期:https://github.com/golang/go/wiki/Go-Release-Cycle
    3. 编译器自举过程
  • 安装 Go:https://gist.github.com/Dids/dbe6356377e2a0b0dc8eacb0101dc3a7

  • https://github.com/golang/go/issues/42684

    • 内核恐慌的第 62 期:你的电脑不是你的,代码签名,OCSP Server
    • ken thompson 图灵奖演讲:reflections on trusting trust
      • TODO
    • 苹果代码签名的老问题,早年做 electron 也是这类问题,现在这样的问题还是存在
  • 异步抢占随机崩溃,是 Rosetta 的 Bug:https://github.com/golang/go/issues/42700

  • 自居,安装的困惑:https://github.com/golang/go/issues/38485#issuecomment-735360572

    • Go 语言的自举分为三个步骤
        1. 1.4 C version TODO
        1. tool chain 1
        1. tool chain 2
        1. tool chain 3
  • 在 Rosetta 下运行 x86 程序:arch --x86_64

  • dotfiles 中关于 M1 的兼容性情况:https://github.com/changkun/dotfiles/issues/2

    • https://doesitarm.com/
    • https://isapplesiliconready.com/
  • 十二月初入手 如今已经使用快两个月了 非常流畅 续航逆天

  • 我的必备第三方软件列表:

    • homebrew (支持性不好,好在现在大部分依赖的软件是用 Go 写的,而且 Go 的支持非常完善)
      • 不考虑兼容性 随意破坏兼容性移除软件分发,有一个 rmtrash 的工具,我从2014年左右就开始使用,但是去年被从软件分发中移除了,所以自己写了一个全兼容的工具changkun.de/s/rmtrash,但没有被合并,他们说了要被原软件作者任何才能不受受欢迎程度的限制,但实际上软件作者已经联系不到了
    • vscode(已在长期使用 Insider)
    • macvim
    • tmux
    • oh-my-zsh
    • Blender(Cycles 光追渲染不支持 GPU,但编辑顶点小于百万级别的网格是没有问题的)
    • iTerm:支持 M1
    • Chrome:支持 M1
    • MacTex:支持 M1
    • Docker:圣诞节前一周发布支持,很完美,至今没有遇到问题
  1. Go Modules 的变更

    1. 收集反馈
    2. 复杂依赖管理,你实践中管理过最复杂的项目依赖多少模块,每次依赖升级都有写什么?在没有 Go modules 之前你用的是什么?
      1. 我的经历:Go vendor, 1.10 dep, 1.11 go modules,
      2. GOPATH 的项目管理,现在虽然移除了 gopath,但我还是沿用了 gopath 的习惯
    3. 最小版本选择
      1. Semantic Versioning: major.minor.patch
      2. 经典的钻石依赖问题:A依赖B和C,BC分别依赖 D 的不同版本,而这两个版本的 D 不兼容,所以无法在依赖中选取一个特定的D版本,semantic import versioning 消除了这种依赖,在import path的最后添加了主版本号的要求/v2
      3. dep 不允许钻石依赖,升级非常难
      4. 构建的可重复性,没有lock文件,>=的依赖会随着时间的变化而变化
      5. 选择最小的可以依赖的版本,构建不会随时间的变化而变化
      6. https://www.youtube.com/watch?v=F8nrpe0XWRg&ab_channel=SingaporeGophers
      7. 不被理解的工作方式
      8. GOPATH
      9. vendor
      10. 三大要点
      11. 兼容性
      12. 可重复性
      13. 合作(通常被很多人忽略)
    4. 默认启用 Go Moduels, go build 必须包含 go.mod 文件,否则编译失败
    5. build/test 不会升级 modules
    6. 默认 -mod=vendor
  2. 文件系统接口

    1. fs.FS 抽象的重要性在哪里

      1. unix file system abstract always disk blocks
      2. network file systems (upspin) abstract away machines
      3. rest abstract nearly anything
      4. cp 不关心是否移动文件的区块,甚至不关心文件在哪个位置,可能是不同的磁盘也可能是不同的机器
      5. 定义任何文件类型工具的「泛型」
    2. 导致了哪些主要变化

      1. io/ioutil
        1. Russ cox 对 deprecated 在 go 中的解释(https://twitter.com/_rsc/status/1351676094664110082)
        2. https://www.srcbeat.com/2021/01/golang-ioutil-deprecated/
      2. 其他 fs 的抽象
      3. Rob Pike 的 2016/2017 Gopherfest, Upspin、Changkun 的 Midgard
        1. https://www.youtube.com/watch?v=ENLWEfi0Tkg&ab_channel=TheGoProgrammingLanguage
        2. FUSE: filesystem in userspace
        3. https://changkun.de/s/midgard
        4. every user has a private root, no global root, r@golang.org/some/stuff, user names look like email address
        5. access control defined by plain text files read: r@golang.org, ann@example.com
      4. 目前的非常简单的实现,只是一个只读文件系统
      5. ReadDir and DirEntry
        1. https://benhoyt.com/writings/go-readdir/
      6. 可扩展的方向:memoryFS,支持回写到磁盘、hashFS 为 CDN 提供支持
      7. 还存在的问题。。例如 44166
      1
      2
      3
      4
      5
      6
      7
      
      import _ "embed"
      //go:embed a.txt
      var s string
      
      import "embed"
      type embed.String string
      var s embed.String
      
      1
      
      
      
  3. 文件嵌入 //go:embed

    1. 新特性的基本功能
    2. 一些可能的应用
    3. 一些在feature freeze cycle 中才讨论出来的feature
    4. https://blog.carlmjohnson.net/post/2021/how-to-use-go-embed/
  4. 运行时内存管理

    1. 回归 MADV_DONTNEED
    • https://blog.changkun.de/posts/pss-uss-rss/
    1. 新的监控基础设施 runtime/metrics
    • 以前的监控函数:runtime.ReadMemStats, debug.GCStats,
    • runtime/metrics:
      • metrics.All()
      • Issue 37112
 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
package main

import (
	"fmt"
	"runtime/metrics"
)

func main() {
	// Get descriptions for all supported metrics.
	descs := metrics.All()

	// Create a sample for each metric.
	samples := make([]metrics.Sample, len(descs))
	for i := range samples {
		samples[i].Name = descs[i].Name
	}

	// Sample the metrics. Re-use the samples slice if you can!
	metrics.Read(samples)

	// Iterate over all results.
	for _, sample := range samples {
		// Pull out the name and value.
		name, value := sample.Name, sample.Value

		// Handle each sample.
		switch value.Kind() {
		case metrics.KindUint64:
			fmt.Printf("%s: %d\n", name, value.Uint64())
		case metrics.KindFloat64:
			fmt.Printf("%s: %f\n", name, value.Float64())
		case metrics.KindFloat64Histogram:
			// The histogram may be quite large, so let's just pull out
			// a crude estimate for the median for the sake of this example.
			fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram()))
		case metrics.KindBad:
			// This should never happen because all metrics are supported
			// by construction.
			panic("bug in runtime/metrics package!")
		default:
			// This may happen as new metrics get added.
			//
			// The safest thing to do here is to simply log it somewhere
			// as something to look into, but ignore it for now.
			// In the worst case, you might temporarily miss out on a new metric.
			fmt.Printf("%s: unexpected metric Kind: %v\n", name, value.Kind())
		}
	}
}

func medianBucket(h *metrics.Float64Histogram) float64 {
	total := uint64(0)
	for _, count := range h.Counts {
		total += count
	}
	thresh := total / 2
	total = 0
	for i, count := range h.Counts {
		total += count
		if total > thresh {
			return h.Buckets[i]
		}
	}
	panic("should not happen")
}
  1. 其他值得一提的特性
    1. os/signal.NotifyContext
    2. 内存模型修复
    3. 链接器优化

Are PSS/USS and RSS Actually the Same Thing?PSS/USS 和 RSS 其实是一回事,吗?

Published at发布于:: 2021-01-23   |   Reading阅读:: 15 min
Since Go 1.12, there have been a steady stream of false-alarm monitoring incidents. The root cause is that starting with Go 1.12, Go changed the memory reclamation strategy used in madvise system calls from MADV_DONTNEED to MADV_FREE. Based on available documentation, RSS — the most commonly used memory monitoring metric — does not reflect the portion of memory that has been released by the process but not yet reclaimed by the OS.
Read More阅读更多 »

Performance Differences from Page Faults vs. Prefetching缺页与预取带来的性能差异

Published at发布于:: 2021-01-18   |   Reading阅读:: 11 min
Just how large can the performance difference caused by page faults be? Let’s write a benchmark to find out. Simulating Page Fault Behavior To build this benchmark, we need to understand two low-level Linux syscalls for memory management: mmap and madvise. For memory allocation, mmap can be called with the anonymous and private mapping flags MAP_ANON and MAP_PRIVATE. Memory allocated this way is in a page-fault state — any access to the allocated region will trigger a page fault.
Read More阅读更多 »
idea想法 2021-01-18 00:00:00

Daily Reading每日阅读

Read these articles:

  • What to expect when monitoring memory usage for modern Go applications. https://www.bwplotka.dev/2019/golang-memory-monitoring/
  • Distributed Systems. https://www.youtube.com/watch?v=UEAMfLPZZhE
  • Golang News. https://www.golangnews.com/
  • SIGCHI Symposium on Engineering Interactive Computing Systems. http://eics.acm.org/
  • runtime: use MADV_FREE on Linux if available. https://go-review.googlesource.com/c/go/+/135395/
  • runtime: make the page allocator scale. https://github.com/golang/go/issues/35112
  • runtime: add per-p mspan cache. https://go-review.googlesource.com/c/go/+/196642
  • A New Smoothing Algorithm for Quadrilateral and Hexahedral Meshes. https://link.springer.com/content/pdf/10.1007%2F11758525_32.pdf
  • OpenGL Docs. https://docs.gl
  • On Playing Chess. https://blog.gardeviance.org/2018/03/on-playing-chess.html
  • Memory Models: A Case For Rethinking Parallel Languages and Hardware. https://cacm.acm.org/magazines/2010/8/96610-memory-models-a-case-for-rethinking-parallel-languages-and-hardware/fulltext
  • Engineer level & competency framework. https://github.com/spring2go/engineer_competency_framework
  • A Concurrent Window System. http://doc.cat-v.org/bell_labs/concurrent_window_system/concurrent_window_system.pdf

读了这些文章:

  • 监控现代 Go 应用内存使用时的注意事项。https://www.bwplotka.dev/2019/golang-memory-monitoring/
  • 分布式系统。https://www.youtube.com/watch?v=UEAMfLPZZhE
  • Golang 新闻。https://www.golangnews.com/
  • SIGCHI 交互式计算系统工程研讨会。http://eics.acm.org/
  • runtime:在 Linux 上使用 MADV_FREE(如果可用)。https://go-review.googlesource.com/c/go/+/135395/
  • runtime:使页分配器可扩展。https://github.com/golang/go/issues/35112
  • runtime:添加 per-p mspan 缓存。https://go-review.googlesource.com/c/go/+/196642
  • 一种用于四边形和六面体网格的新平滑算法。https://link.springer.com/content/pdf/10.1007%2F11758525_32.pdf
  • OpenGL 文档。https://docs.gl
  • 论下棋。https://blog.gardeviance.org/2018/03/on-playing-chess.html
  • 内存模型:重新思考并行语言和硬件。https://cacm.acm.org/magazines/2010/8/96610-memory-models-a-case-for-rethinking-parallel-languages-and-hardware/fulltext
  • 工程师等级与能力框架。https://github.com/spring2go/engineer_competency_framework
  • 一个并发窗口系统。http://doc.cat-v.org/bell_labs/concurrent_window_system/concurrent_window_system.pdf
idea想法 2021-01-06 00:00:00

Creating A Window创建一个窗口

How to create a window using Go? macOS has Cocoa, Linux has X11, but accessing these APIs seems to require Cgo. Is it possible to avoid Cgo? Some existing GUI libraries and graphics engines:

GUI Toolkits:

  • https://github.com/hajimehoshi/ebiten
  • https://github.com/gioui/gio
  • https://github.com/fyne-io/fyne
  • https://github.com/g3n/engine
  • https://github.com/goki/gi
  • https://github.com/peterhellberg/gfx
  • https://golang.org/x/exp/shiny

2D/3D Graphics:

  • https://github.com/llgcode/draw2d
  • https://github.com/fogleman/gg
  • https://github.com/ajstarks/svgo
  • https://github.com/BurntSushi/graphics-go
  • https://github.com/azul3d/engine
  • https://github.com/KorokEngine/Korok
  • https://github.com/EngoEngine/engo/
  • http://mumax.github.io/

Here is a partial list:

https://github.com/avelino/awesome-go#gui

Most people use glfw and OpenGL. Here are some required libraries (Cgo bindings):

  • https://github.com/go-gl/gl
  • https://github.com/go-gl/glfw
  • https://github.com/remogatto/egl

Some more low-level ones, e.g. X-related:

  • X bindings: https://github.com/BurntSushi/xgb
  • X window management: https://github.com/BurntSushi/wingo

For example, if you need Metal on macOS:

  • https://dmitri.shuralyov.com/gpu/mtl

Like the GUI tool ebiten mentioned above, on Windows it no longer needs Cgo. The approach seems to be packaging the window management DLLs directly into the binary and then using DLL dynamic linking calls.

Besides GLFW, there is the heavier SDL:

  • https://github.com/veandco/go-sdl2

Relationships between some basic terms:

1
2
3
4
5
6
7
Unix:      The ancestor
BSD:       Unix-like, Berkeley distribution, one of the two traditional flavors of Unix
System V:  Developed by AT&T, one of the two traditional flavors of Unix
Linux:     A fresh flavor of Unix-like OS
POSIX:     A standard attempting to reduce implementation differences
Darwin:    Apple's open-source Unix-like kernel XNU
Mach-O:    Microkernel hybridized in Darwin, developed by CMU

By Eraserhead1, Infinity0, Sav_vas - Levenez Unix History Diagram, Information on the history of IBM's AIX on ibm.com, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=1801948

Relationships between some Wayland-related tools:

1
2
3
4
5
6
X Window System == X11: Display standard developed by MIT, the foundation for GNOME and KDE
Xorg:    The official implementation of X11
Wayland: An alternative communication protocol between display server and client, distinct from X11
EGL:     Wayland clients use EGL to directly manipulate the framebuffer
libDRM:  Kernel API exposed to userspace, underlying dependency of EGL/X11
DRM:     Kernel-level component for manipulating the framebuffer

By Shmuel Csaba Otto Traian, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=28029855

By Shmuel Csaba Otto Traian, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=31768083

By Shmuel Csaba Otto Traian, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27858390

By Shmuel Csaba Otto Traian,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=27799196

So through DRM you can directly operate on the Frame Buffer under Linux, i.e., Direct Rendering Manager. Related libraries:

  • https://github.com/NeowayLabs/drm

With this, you can do pure Go rendering directly on Linux, eliminating the dependency on C legacy.

如何使用 Go 创建一个窗口?macOS 有 Cocoa、Linux 有 X11,但访问这些 API 似乎都需要 引入 Cgo,可不可以不实用 Cgo?一些现有的 GUI 库或这图形引擎:

GUI 工具包:

  • https://github.com/hajimehoshi/ebiten
  • https://github.com/gioui/gio
  • https://github.com/fyne-io/fyne
  • https://github.com/g3n/engine
  • https://github.com/goki/gi
  • https://github.com/peterhellberg/gfx
  • https://golang.org/x/exp/shiny

2D/3D 图形相关:

  • https://github.com/llgcode/draw2d
  • https://github.com/fogleman/gg
  • https://github.com/ajstarks/svgo
  • https://github.com/BurntSushi/graphics-go
  • https://github.com/azul3d/engine
  • https://github.com/KorokEngine/Korok
  • https://github.com/EngoEngine/engo/
  • http://mumax.github.io/

这里有一小部分:

https://github.com/avelino/awesome-go#gui

大部分人的做法是使用 glfw 和 OpenGL,这是一些需要使用到的库(Cgo 绑定):

  • https://github.com/go-gl/gl
  • https://github.com/go-gl/glfw
  • https://github.com/remogatto/egl

这里面有一些相对底层一些的,比如 X 相关:

  • X 绑定:https://github.com/BurntSushi/xgb
  • X 窗口管理:https://github.com/BurntSushi/wingo

比如 macOS 上如果需要用到 Metal:

  • https://dmitri.shuralyov.com/gpu/mtl

像是前面的 GUI 工具中的 ebiten,在 windows 上已经不需要 Cgo 了,做法似乎是将窗口管理相关的 DLL 直接打包进二进制,然后走 DLL 动态链接调用。

除了 GLFW 之外,还有相对重一些的 SDL:

  • https://github.com/veandco/go-sdl2

一些基本名词之间的关系:

1
2
3
4
5
6
7
Unix:      上帝
BSD:       类 Unix,伯克利分发,两种传统风味的 Unix 之一
System V:  AT&T 开发,两种传统风味的 Unix 之一
Linux:     新鲜风味的类 Unix
POSIX:     尝试减少实现差异的标准
Darwin:    苹果的开源类 Unix 内核 XNU
Mach-O:    Darwin 混合的微内核,CMU 开发

By Eraserhead1, Infinity0, Sav_vas - Levenez Unix History Diagram, Information on the history of IBM's AIX on ibm.com,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=1801948

关于 Wayland 的一些工具之间的关系:

1
2
3
4
5
6
X Window System == X11: MIT 开发的显示标准,GNOME、KDE 依赖的基础
Xorg:    X11 的官方实现
Wayland: 另一种显示服务器和客户端之间的通信协议,区别于 X11
EGL:     Wayland 客户端使用 EGL 来直接操作 framebuffer
libDRM:  EGL/X11 底层依赖的内核对 userspace 开放的 API
DRM:     内核级操作 framebuffer 的组件

By Shmuel Csaba Otto Traian, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=28029855

By Shmuel Csaba Otto Traian, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=31768083

By Shmuel Csaba Otto Traian, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=27858390

By Shmuel Csaba Otto Traian,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=27799196

所以通过 DRM 可以在 Linux 下直接操作 Frame Buffer 上,也就是 Direct Rendering Manager。相关的库有:

  • https://github.com/NeowayLabs/drm

有了这个就可以在 Linux 上直接做纯 Go 的绘制了,从而消除对 C 遗产的依赖。

idea想法 2021-01-05 00:00:00

Daily Reading每日阅读

Read these articles:

  • The Right to Read. https://www.gnu.org/philosophy/right-to-read.en.html
  • Your Computer Isn’t Yours. https://sneak.berlin/20201112/your-computer-isnt-yours/
  • Pirate Cinema. https://craphound.com/pc/download/

Noticed these two clipboard-related projects:

  • https://github.com/binwiederhier/pcopy
  • https://github.com/nakabonne/pbgopy

It seems their development timelines are very close to when I developed midgard, but we all took very different paths:

  • pcopy focuses on the clipboard itself, with features like password protection, multiple clipboards, WebUI, etc.
  • pbgopy emphasizes security for cross-device syncing, with various key configurations, but very simple functionality — only supports text

The midgard I developed focuses on these features:

  • Automatic cross-device syncing (clipboard write-back), no commands needed
  • Ability to query devices currently online
  • Supports not only text but also image syncing
  • Supports creating public URLs for clipboard content
  • Supports converting code in clipboard to Carbon images
  • Supports keyboard shortcuts
  • …

读了这几篇文章:

  • 阅读的权利。https://www.gnu.org/philosophy/right-to-read.en.html
  • 你的电脑不属于你。https://sneak.berlin/20201112/your-computer-isnt-yours/
  • 盗版电影院。https://craphound.com/pc/download/

注意到了这两个跟剪贴板相关的项目:

  • https://github.com/binwiederhier/pcopy
  • https://github.com/nakabonne/pbgopy

看起来他们开发这两个项目的时间跟我开发 midgard 的时间非常接近,不过大家都走了很不同的路线:

  • pcopy 着重剪贴板本身,比如有剪贴板的密码保护,多种剪贴板、WebUI 等特性
  • pggopy 注重设备间同步的安全性,有各种密钥配置,但功能非常简单,只支持文本

我开发的 midgard 的则主打这些特性:

  • 多设备间自动同步(剪贴板回写),不需要敲命令
  • 能够查询同时在线的设备
  • 不仅支持文本,还支持图片的同步
  • 支持对剪贴板中的内容创建公开的 URL
  • 支持剪贴板中的代码转 Carbon 图片
  • 支持键盘快捷键
  • …

2020 Year-End Review2020 年终总结

Published at发布于:: 2021-01-03   |   Reading阅读:: 22 min
2020 is finally, completely over. As I have done every year since undergraduate, I open my blog and sit down to write this annual reflection. So much seemed to happen this year — I was still in the office working overtime on the very last day of it. If I had to name the single greatest takeaway from 2020, I would distill it to two words: transformation. At the doctoral stage, one can no longer simply expand the breadth of one’s skills the way you could as an undergraduate or master’s student.
Read More阅读更多 »
idea想法 2020-12-31 00:00:00

Daily Reading每日阅读

Read these articles:

  • A History of the GUI. http://www.cdpa.co.uk/UoP/Found/Downloads/reading6.pdf, https://www.readit-dtp.de/PDF/gui_history.pdf
  • History of the graphical user interface. https://en.wikipedia.org/wiki/History_of_the_graphical_user_interface
  • Algebraic Effects for the Rest of Us. https://overreacted.io/zh-hans/algebraic-effects-for-the-rest-of-us/
  • What does algebraic effects mean in FP? https://stackoverflow.com/questions/49626714/what-does-algebraic-effects-mean-in-fp
  • A Distributed Systems Reading List. https://dancres.github.io/Pages/
  • Tutte Embedding for Parameterization. https://isaacguan.github.io/2018/03/19/Tutte-Embedding-for-Parameterization/
  • Commentary on the Sixth Edition UNIX Operating System. http://www.lemis.com/grog/Documentation/Lions/index.php
  • Personal knowledge management beyond versioning. https://dl.acm.org/doi/10.1145/2362456.2362492
  • The Plain Text Life: Note Taking, Writing and Life Organization Using Plain Text Files. http://www.markwk.com/plain-text-life.html
  • Post-Evernote: How to Migrate Your Evernote Notes, Images and Tags Into Plain Text Markdown. http://www.markwk.com/migrate-evernote-plaintext.html
  • Five Levels of Error Handling in Both Python and JavaScript. https://dev.to/jesterxl/five-levels-of-error-handling-in-both-python-and-javascript-13ok

读了这些文章:

  • GUI 的历史。http://www.cdpa.co.uk/UoP/Found/Downloads/reading6.pdf, https://www.readit-dtp.de/PDF/gui_history.pdf
  • 图形用户界面的历史。https://en.wikipedia.org/wiki/History_of_the_graphical_user_interface
  • 写给普通人的代数效应。https://overreacted.io/zh-hans/algebraic-effects-for-the-rest-of-us/
  • 代数效应在函数式编程中意味着什么?https://stackoverflow.com/questions/49626714/what-does-algebraic-effects-mean-in-fp
  • 分布式系统阅读清单。https://dancres.github.io/Pages/
  • 用于参数化的 Tutte 嵌入。https://isaacguan.github.io/2018/03/19/Tutte-Embedding-for-Parameterization/
  • 第六版 UNIX 操作系统注释。http://www.lemis.com/grog/Documentation/Lions/index.php
  • 超越版本控制的个人知识管理。https://dl.acm.org/doi/10.1145/2362456.2362492
  • 纯文本生活:使用纯文本文件进行笔记、写作和生活管理。http://www.markwk.com/plain-text-life.html
  • 后 Evernote 时代:如何将 Evernote 笔记、图片和标签迁移到纯文本 Markdown。http://www.markwk.com/migrate-evernote-plaintext.html
  • Python 和 JavaScript 中错误处理的五个层次。https://dev.to/jesterxl/five-levels-of-error-handling-in-both-python-and-javascript-13ok
idea想法 2020-12-30 00:00:00

Daily Reading每日阅读

Read these articles:

  • The UNIXHATERS Handbook. http://web.mit.edu/~simsong/www/ugh.pdf
  • Why are video games graphics (still) a challenge? Productionizing rendering algorithms. https://bartwronski.com/2020/12/27/why-are-video-games-graphics-still-a-challenge-productionizing-rendering-algorithms/
  • BPF and Go: Modern forms of introspection in Linux. https://medium.com/bumble-tech/bpf-and-go-modern-forms-of-introspection-in-linux-6b9802682223
  • Systems design explains the world: volume 1. https://apenwarr.ca/log/20201227
  • Error handling guidelines for Go. https://jayconrod.com/posts/116/error-handling-guidelines-for-go
  • The Missing Semester of Your CS Education. https://missing.csail.mit.edu/
  • Build your own React. https://pomb.us/build-your-own-react/

读了这些文章:

  • UNIX 憎恨者手册。http://web.mit.edu/~simsong/www/ugh.pdf
  • 为什么电子游戏图形(仍然)是一个挑战?渲染算法的产品化。https://bartwronski.com/2020/12/27/why-are-video-games-graphics-still-a-challenge-productionizing-rendering-algorithms/
  • BPF 与 Go:Linux 中的现代内省方法。https://medium.com/bumble-tech/bpf-and-go-modern-forms-of-introspection-in-linux-6b9802682223
  • 系统设计解释世界:第一卷。https://apenwarr.ca/log/20201227
  • Go 错误处理指南。https://jayconrod.com/posts/116/error-handling-guidelines-for-go
  • 计算机科学教育中缺失的一课。https://missing.csail.mit.edu/
  • 构建你自己的 React。https://pomb.us/build-your-own-react/
1 2 3 4 5 6 7 8 9
© 2008 - 2026 Changkun Ou. All rights reserved.保留所有权利。 | PV/UV: /
0%