书单记录

这个post为记录目前正在阅读与研究的section Go语言设计 Go语言设计与实现 Go Under The Hood 这两本在写作目的和内容规划都是一致的,不过第二个原本不再维护内容,作者开了下面的新的项目,把撰写原本而积累的与Go相关的资源进行了重新的整理。 Go设计历史 pprof对服务端性能影响的研究 考虑一些极端场景,比如极度追求性能,压榨系统资源以及技术栈必须是Go的业务场景下,是否能自己构建Reactor网络模型 GRPC框架对服务侧性能的影响 Russ Cox正则表达式系列 You should not be permitted to write production code if you do not have an journeyman license in regular expressions or floating point math. – Rob Pike Regular Expression Matching Can Be Simple And Fast 编译器词法分析:正则语言和正则表达式 Go内存原理与调度模型 正在整理专栏 Bound Checking Elimination Crafting Interpreter 时常看PL和Compiler的基础 crafting interpreters Kosaraju’s Algorithm 看William Lin的coding interview觉得用来处理树和图很好,算法4里也有 Heilmeier问题系列 思考某篇paper的选题 What are you trying to do? Articulate your objectives using absolutely no jargon. How is it done today, and what are the limits of current practice? Who cares? [Support other’s research? Shape research landscape? Power applications in industry?] What’s new in your approach and why do you think it will be successful? If you’re successful, what difference will it make? [e.g. Contributions in theory/modeling? Improve accuracy by 5% on dataset A, B, C…?] What are the risks and the payoffs? [Further, how would you mitigate the risks? If your proposed method does not work, what could be alternative design? These can end up as discussions such as ablation studies in your paper.] How much will it cost? [e.g. How many GPUs do your experiments require? How long is each training process? How about data storage?] How long will it take? [How many hours are you going to work on this per week? When is the submission DDL? Can you make it?] What are the midterm and final “exams” to check for success?

December 19, 2020 · 2 min · 239 words · Me

Golang TDD

Preface 本文整理golang编码的单元测试常用示例,以及TDD的简要流程。 单元测试基础 单元测试文件以_test.go结尾,需要记住以下原则: 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码 你必须import testing这个包 所有的测试用例函数必须是Test开头 测试用例会按照源代码中写的顺序依次执行 测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态 测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。 函数中通过调用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。 Table-Driven-Testing 测试讲究 case 覆盖,当我们要覆盖更多 case 时,显然通过修改代码的方式很笨拙。这时我们可以采用 Table-Driven 的方式写测试,标准库中有很多测试是使用这种方式写的。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func TestFib(t *testing.T) { var fibTests = []struct { in int // input expected int // expected result }{ {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}, {7, 13}, } for _, tt := range fibTests { actual := Fib(tt.in) if actual != tt.expected { t.Errorf("Fib(%d) = %d; expected %d", tt.in, actual, tt.expected) } } } 由于我们使用的是 t.Errorf,即使其中某个 case 失败,也不会终止测试执行。 ...

December 19, 2020 · 17 min · 3480 words · Me

Golang并发调度

性能提升不会凭空出现,它总是伴随着代码复杂度的上升。 The performance improvement does not materialize from the air, it comes with code complexity increase. – Dmitry Vyukov Go 语言的调度器我认为应该是整个运行时最有趣的组件了。对于Go本身,它的设计和实现直接牵动了Go运行时的其他组件,也是和用户态代码直接打交道的部分;对于Go用户而言,调度器将其极为复杂的运行机制隐藏在了简单的关键字go下。为了保证高性能,调度器必须有效得利用计算的并行性和局部性原理;为了保证用户态的简洁,调度器必须高效得对调度用户态不可见的网络轮训器、垃圾回收器进行调度;为了保证代码执行的正确性,必须严格实现用户态代码的内存顺序等。总而言之,调度器的设计直接决定了Go运行时源码的表现形式。 设计原理 数据结构: MPG 调度器启动 创建Goroutine 调度循环 触发调度 线程管理 总结

December 17, 2020 · 1 min · 30 words · Me

Python类自定义

python类关键字 __init__ vs __new__ __init__为初始化方法,__new__为真正的构造函数。 描述符Descriptor __contains__ __slots__ 定制类 type() python作为动态语言,和静态语言最大的不同,即函数和类的定义,不是编译的时候创建的而是动态创建的。我们常见的对类的定义: 1 2 3 class Hello(object): def hello(self, name='world'): print('Hello, %s.' % name) >>> from hello import Hello >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class 'hello.Hello'> type()函数可以查看一类类型或者变量的类型,Hello是一个class, 它的类型是个type,而h是一个instance, 它的类型就是class Hello。 同时有一个概念,就是type()不仅可以返回对象的类型,还可以创建出新的类型。我们可以不用定义class Hello() ...而动态创建出Hello类。 >>> def fn(self, name='world'): # 先定义函数 ... print('Hello, %s.' % name) ... >>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class >>> h = Hello() >>> h.hello() Hello, world. >>> print(type(Hello)) <class 'type'> >>> print(type(h)) <class '__main__.Hello'> 创建一个class对象,type()函数传入3个参数: ...

December 14, 2020 · 3 min · 490 words · Me

BDD: Ginkgo测试框架

Preface BDD和TDD都是test case first的实现,无非是把后者的test改成前者的behavior。在TDD中,关注的核心点是function,即认为程序最基本单元是function,其test case可以认为是unit test,TDD和unit test的区别是TDD强调测试和开发结合而成的工作流: 写test case -> 写代码 -> 通过测试,继续写更多测试,写一次循环。 而BDD比TDD更关注高层的行为,而不是函数级别的行为,也就是在BDD中,不会强调函数的功能正确,这是unit test应该做的事。BDD更关注user story,即用户在特定场景,与软件交互发生的行为,这个behavior指的就是高层模块的行为。 如何区分BDD和TDD,简单理解,TDD是给programmer的,用来验证开发者的最基本模块的功能:在什么输入,应该产生什么输出,保证实现的边界,健全性。而BDD,其test case描述的是更高级的模块行为,脱离了具体的实现,容易用自然语言去描述,也就是BDD是给product manager的,告诉其系统的行为。 BDD in golang ​ 实现的时候,我们需要把Given-When-Then这种story格式组织test case翻译为测试代码,通过一系列的assertion来检查实现是否符合test case的预期,我们完全可以直接通过golang自带的testing模块来实现,不过testing的功能有时候比较简陋,本文记录了用Ginkgo+Gomega来组织test case,让我们的测试语言更加接近自然语言。 二者结合的目的是,ginkgo实现了test case的组织,并加入了其他方便的功能: 初始化,后续处理,异步等等。而gomega设计的目的是与ginkgo一起工作,实现易读的assertion(ginkgo中称为match)功能。 Gomega is ginkgo's preferred matcher library 初始化 ginkgo依托golang原生testing框架,即可以用go test ./.. 执行,也可以通过ginkgo binrary安装go install github.com/onsi/ginkgo,封装了ginkgo测试框架的各种feature。 初始化首先进入待测试的package: cd /path/to/package 执行初始化: ginkgo bootstrap 生成以suite_test.go文件,接下来向suite添加测试specs,生成比如ginkgo_cart package测试文件。 ginkgo generate ginkgo_cart 运行 生成ginkgo_cart_test.go,注意测试文件在ginkgo_cart_testpackage, 需要import package ginkgo_cart,即BDD层级高于unit test, 不应该了解package内部的具体实现,测试package的外部接口即可。编写测试代码,运行go test ./..即可。 Ginkgo Keyword Ginkgo测试代码骨架由一系列keyword关联的闭包组成,常用的有: Describe/Context/When: 测试逻辑块 BeforeEach/AfterEach/JustBeforeEach/JustAfterEach: 初始化测试用例块 It: 单一Spec,测试case keyword的声明均为传入Body参数,比如Describe: ...

December 4, 2020 · 2 min · 395 words · Me