Toml to Golang Struct
之前写某个东西的副产品,本质上和 https://xuri.me/toml-to-go/ 一样。
解析 Toml 仍然依赖 github.com/BurntSushi/toml 这个库。
之前写某个东西的副产品,本质上和 https://xuri.me/toml-to-go/ 一样。
解析 Toml 仍然依赖 github.com/BurntSushi/toml 这个库。
之前写了一篇分析 uber 的 automaxprocs 的源码,后面抽个了时间写了一个 C++ 版本的。
其一是为了加深对原库的理解;其二是避免太长时间没写 C++ 手生,以及顺带体验一下 C++ 17 的感觉。
代码在:https://github.com/kingsamchen/Eureka/tree/master/auto-cfs-cores
最近直播内部的 golang 服务都使用了 uber 出品的 automaxprocs 这个库。
据伟大的 @ice 马总说,这个库解决了一个困扰B站整个golang(container)技术栈一年多的问题。
出于好奇这个库到底做了什么 magic,能够解决这个持续了一年多的 pain in the ass,抽了一点时间,稍微翻了一下库的源代码,记录如下。
线上容器里的服务通常都对 CPU 资源做了限制,例如默认的 4C。
但是在容器里通过 lscpu
仍然能看到宿主机的所有 CPU 核心:
1 | rchitecture: x86_64 |
这就导致 golang 服务默认会拿宿主机的 CPU 核心数来调用 runtime.GOMAXPROCS()
,导致 P 数量远远大于可用的 CPU 核心,引起频繁上下文切换,影响高负载情况下的服务性能。
本文是对 Jeff Preshing 的 Double Checked Locking Is Fixed in C++ 11 笔记。
因为 synchronization 只需要在实例第一次创建时保证;此后( instance != nullptr
时)都不需要锁来保证 synchronization。
在第一次判断实例为空和上锁之间存在一个 potential race,因此上锁后需要再一次判断实例是否为空。
这也是 double checked 的来由。
所以一个传统但并不100%正确的 DCLP 实现如下:
1 | class Singleton { |
这基本是早起 C++ DCLP 的实现架子。
语句
1 | instance = new Singleton(); |
在 C++ 中实际上等效于
1 | tmp = operator new(sizeof(Singleton)); // step 1: allocate memory via operator new |
注意:其中除了分配内存是固定第一步之外,构造对象和赋值内存地址的生成代码顺序是由编译器自己决定。这里的顺序只是一种可能性。
近段有相当一部分时间在熟悉和练习 ASIO。
练习过程中发现 ASIO 中如何使用&管理 buffer 是新手大概率会遇到的问题。
结合最近几个 practice demo,稍微简单总结了一下使用经验:
0x00
const_buffer
和 mutable_buffer
是两个 fundamental buffer classes。二者的区别在语义上表达的很明显了。
实现上二者提供的接口非常一致,除了一个面向 const void*
,另一个面向 void*
。这点可以从 ctor 和 data()
中看出。
另外,为了和 C++ 现有的 const cast semantics 保持一致,一个 mutable_buffer
对象可以 implicitly converted to const_buffer
。