From ad76ec4378a4e1ae6b3c49253e54720827302959 Mon Sep 17 00:00:00 2001 From: Ted Mostly Date: Mon, 4 Dec 2023 15:12:18 +0800 Subject: [PATCH] 140 (#82) * update * update * update * update * tag pointer --- README.md | 11 +- posts/139.md | 2 +- posts/140.md | 386 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 393 insertions(+), 6 deletions(-) create mode 100644 posts/140.md diff --git a/README.md b/README.md index 75e6313..49e883b 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ RSS使用仓库的release RSS [链接](https://github.com/wanghenshui/cppweeklyn ## 2023 -| [131](./posts/131.md) | [132](./posts/132.md) | [133](./posts/133.md) | [134](./posts/134.md) | [135](./posts/135.md) | [136](./posts/136.md) | [137](./posts/137.md) | [138](./posts/138.md) | [139](./posts/139.md) | | +| [131](./posts/131.md) | [132](./posts/132.md) | [133](./posts/133.md) | [134](./posts/134.md) | [135](./posts/135.md) | [136](./posts/136.md) | [137](./posts/137.md) | [138](./posts/138.md) | [139](./posts/139.md) | [140](./posts/140.md) | | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | | [121](./posts/121.md) | [122](./posts/122.md) | [123](./posts/123.md) | [124](./posts/124.md) | [125](./posts/125.md) | [126](./posts/126.md) | [127](./posts/127.md) | [128](./posts/128.md) | [129](./posts/129.md) | [130](./posts/130.md) | | [111](./posts/111.md) | [112](./posts/112.md) | [113](./posts/113.md) | [114](./posts/114.md) | [115](./posts/115.md) | [116](./posts/116.md) | [117](./posts/117.md) | [118](./posts/118.md) | [119](./posts/119.md) | [120](./posts/120.md) | @@ -66,7 +66,7 @@ RSS使用仓库的release RSS [链接](https://github.com/wanghenshui/cppweeklyn - 杨杰 - 阿刚 - MSK -- 不语 x23 +- 不语 x24 - ywp - 范天泷 - 罗盛波 @@ -82,12 +82,13 @@ RSS使用仓库的release RSS [链接](https://github.com/wanghenshui/cppweeklyn - 许琦 - 高博 - Yin x2 -- YellyHornby x2 +- YellyHornby x3 - 404 - Amnesia x2 - fengyiee木马 - 陈青松 -- 黄亮Anthony x3 +- 黄亮Anthony x4 - Captain - Anien -- jerry \ No newline at end of file +- jerry +- HNY \ No newline at end of file diff --git a/posts/139.md b/posts/139.md index 5b1b4e2..fec4894 100644 --- a/posts/139.md +++ b/posts/139.md @@ -339,7 +339,7 @@ int main() { - [asteria](https://github.com/lhmouse/asteria) 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线 -最近进展,发现自旋竟然比metux还慢,还在研究 +最近进展,发现 cmpxchg16b 不该用。竟然比mutex还慢,还在研究 - [Unilang](https://github.com/linuxdeepin/unilang) deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了 diff --git a/posts/140.md b/posts/140.md new file mode 100644 index 0000000..aa1ec0d --- /dev/null +++ b/posts/140.md @@ -0,0 +1,386 @@ +--- +layout: post +title: 第140期 +--- +# C++ 中文周刊 第140期 + + +[周刊项目地址](https://github.com/wanghenshui/cppweeklynews) + +公众号 + + + +qq群 [手机qq点击进入](https://qm.qq.com/q/6NGizNPyG4) + +RSS https://github.com/wanghenshui/cppweeklynews/releases.atom + +欢迎投稿,推荐或自荐文章/软件/资源等 + +请[提交 issue](https://github.com/wanghenshui/cppweeklynews/issues) + + +最近在找工作准备面试题,更新可能有些拖沓,见谅 + +本周内容比较少 + +本期文章由 YellowHornby HNY 不语 黄亮Anthony 赞助 + +--- + + +## 资讯 + +标准委员会动态/ide/编译器信息放在这里 + + +编译器信息最新动态推荐关注hellogcc公众号 [OSDT Weekly 2023-11-29 第230期 ](https://mp.weixin.qq.com/s/wVUx7x4Ras0gJ3DnxlUnYw) + + +## 文章/视频 + +- [On harmful overuse of std::move](https://devblogs.microsoft.com/oldnewthing/20231124-00/?p=109059) + +能返回值优化,不move + +- [记一次深入内核的数据库高并发性能优化实践](https://zhuanlan.zhihu.com/p/669173594) + +定位到 mmap_sem 互斥锁冲突,查找来源 + +哪里会有mmap? +- 内存分配器 ptmalloc / tcmalloc 大页 +- fopen/fseek? + +逐个排除定位到是fseek内部有mmap,新版本glibc已经去掉了mmap改了回来,打patch + +那么为什么fseek会调用mmap呢?就不能malloc吗 buffer能多大? + +本台记者Anein分析是历史原因,为了初始化不清空0,用mmap偷懒了一下。原来大家都偷懒 + +- [深入浅出 LLVM之 DenseMap 源码解析](https://zhuanlan.zhihu.com/p/669307116) + +densemap就是flatmap- + +- [写出让人不想维护的 C++ 代码之是给我 API 的人先动手的: `manually_drop` 和玩弄访问权限](https://zhuanlan.zhihu.com/p/667689874) + +看个乐,别学。还是friend注入那套玩意儿 + +- [Integer overflow and arithmetic safety in C++](https://orodu.net/2023/11/29/overflow.html) + +整型溢出似乎没有好的解决办法,除了多注意/自定义类型加边界检查 + +介绍了其他语言的解决方法,比如rust 的 overflowing_mul overflowing_add + +google内部也有类似的库设计 https://github.com/chromium/subspace/pull/410/files + +似乎除了这些,没有更好的办法? + + +- [Lightning Talk: Type-safe Dictionaries - Vincent Tourangeau - CppNorth 2023](https://www.youtube.com/watch?v=i9p_qFW6hJ4) + +一个幽默的typemap + +说到typemap映射,第一反应是字符串/typeindex?是的他就这么实现的,不过用了匿名的类 + +typeindex计算是很慢的。数量大不建议这么玩,这里展示这种可能性 + +```c++ +#include +#include +#include +#include +#include +#include + + +using dict = std::map; + +template +struct key final { explicit key() = default;}; + +template +auto get(const dict& d, key k) ->std::optional { + if (auto pos = d.find(typeid(k)); pos!=d.end()) { + return std::any_cast(pos->second); + } + return std::nullopt; +} + +template +void set(dict& d, key k, V&& v) { + constexpr bool convertible = std::is_convertible_v; + static_assert(convertible); + if constexpr (convertible) { + d.insert_or_assign(typeid(k), T{std::forward(v)}); + } +} + + +// key里面的类可以只声明不实现,当tag用,只要唯一就行 +using age_k = key; +using gender_k = key>; +using name_k = key; + +constexpr inline auto age = age_k{}; +constexpr inline auto gender = gender_k{}; +constexpr inline auto name = name_k{}; + +int main() { + auto person = dict(); + set(person, age, 14); + set(person, gender,std::pair{0.5,0.5}); + set(person, name,"ted"); + const auto a = get(person, age); + const auto g = get(person, gender); + const auto n = get(person, name); + std::cout <<*a <first << g->second << *n<<"\n"; +} + +``` + +https://godbolt.org/z/z1hvxzf1e 可以自己玩一下 + +如果真要考虑用,首先不能用typeindex,得实现一个类转字符串,还得保证唯一性,然后用hashmap存就行 + +另外不用std::any,用create函数之类的代替 + +这种需求感觉游戏行业有这种场景 + +- [Compile-time Bounds Checking in Flux](https://tristanbrindle.com/posts/compile-time-bounds-checking-in-flux) + +对于array,编译期检查越界应该是可能的 + +```c++ +int get_last_elem(const std::array& arr) { + return arr.at(5); // oops, off-by-one +} + +``` + +这种明显越界,编译期能不能抓到?能,但不报错,会直接抛异常,编译器比较信任你,觉得你喜欢异常 + +```asm +get_last_elem(std::array const&): # @get_last_elem(std::array const&) + push rax + lea rdi, [rip + .L.str] + mov esi, 5 + mov edx, 5 + xor eax, eax + call std::__throw_out_of_range_fmt(char const*, ...)@PLT +``` + +flux库写了个编译期检查的设计 + +```c++ +int get_last_elem(const std::array& arr) { + return flux::read_at(arr, 5); // oops, off-by-one +} + +``` +编译期就抓到直接报错,如何实现? + +```c++ +[[gnu::error("out-of-bounds sequence access detected")]] +void static_bounds_check_failed(); + + +template +void bounds_check(Index idx, Index limit) +{ + if (__builtin_constant_p(idx) && __builtin_constant_p(limit)) { + if (idx < Index{0} || idx >= limit) { + /* ...report error at compile time... */ + } + } else { + /* ...perform normal run-time bounds check... */ + } + +``` + +但存在问题,__builtin_constant_p并不是那么可信 + +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112296 + +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89029 + +只能说,缘分相信编译器,可能帮你一下 + +- [Compiler Options Hardening Guide for C and C++](https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html) + +安全加固的编译配置 + +```shell +-O2 -Wall -Wformat=2 -Wconversion -Wtrampolines -Wimplicit-fallthrough \ +-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \ +-D_GLIBCXX_ASSERTIONS \ +-fstrict-flex-arrays=3 \ +-fstack-clash-protection -fstack-protector-strong \ +-Wl,-z,nodlopen -Wl,-z,noexecstack \ +-Wl,-z,relro -Wl,-z,now +``` + +FORTIFY有性能影响 + +这些还是要关注一下性能影响,中间三行有影响。如果某些行业必须加固那也没办法 + + +- [Storing data in pointers](https://muxup.com/2023q4/storing-data-in-pointers) + +tag pointer + +指针一般8字节64bits,只用48bits表示内存空间,剩下的16bits有很多可以倒腾的空间,嵌入一些信息 + +提问: 48bit能表示多大内存? + +剩下的这16bit能做什么文章? +- x86_64 加标志位区分内核内存还是用户态内存 +- rsicv也有类似设计 +- arm是49位内存,其他设计也是类似的 + +各种硬件系统还有自己的其他设计,利用bit,这里就不展开了 + +- Intel 有 Linear Address Masking (LAM) +- AMD有 Upper Address Ignore +- rsicv有 pointer masking extension +- arm有 Top Byte Ignore (TBI) + + +这波报菜名大部分都没什么接触的机会。 + +考虑自定义的场景 + +- fixie trie 用不到的16位用来做bitmap +- llvm pointpairpointer 其实有点union双关用法了 https://github.com/llvm/llvm-project/blob/dc8b055c71d2ff2f43c0f4cac66e15a210b91e3b/llvm/include/llvm/ADT/PointerIntPair.h#L64 + - 暴论 tag pointer 就是union +- 显然 ZGC的pointer设计也是tag pointer https://dinfuehr.github.io/blog/a-first-look-into-zgc/ +- 显然 objc和go的tag pointer自然都是,这俩比较有名,就不列了 +- 当然 v8 中的pointer compression 自然也是 tag pointer https://v8.dev/blog/pointer-compression +- 那么异或链表自然也是tag pointer +- 当然酒店传单也是tag pointer,不仅可以订餐还可以点按摩是不是 + + + +- [Lightning Talk: When C++ Managers Fail... Richard Shepherd - C++ on Sea 2023](https://www.youtube.com/watch?v=2T5dIwAXCqc) + +重新考虑单例实现 + +static 单例 static保证 `成功` `创建` `一次` + +那么存在构造函数抛异常的可能性。注意你的单例的T是不是可能构造抛异常 + +可能挽救一下就成了这个德行 + +```c++ +class Manager { + Resouce* resource_; + Manager() : resource_{CreateResource()} { + if (!resource_) { + throw std::exception("Not ready") + } + } + public: + + static Manager* Instance() { + try { + static Manager s; + return &s; + } catch (...) { + return nullptr; + } + } +}; +``` + +## 只展示代码段,没啥别的说的 + +- [A Priority Scheduler for Coroutines](https://www.modernescpp.com/index.php/a-priority-scheduler-for-coroutines/) + +简单加个优先级,是的,没错,用priority_queue + +```c++ +#include +#include +#include +#include + +struct Task { + struct promise_type { + std::suspend_always initial_suspend() noexcept { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + + Task get_return_object() { + return std::coroutine_handle::from_promise(*this); + } + void return_void() {} + void unhandled_exception() {} + }; + + Task(std::coroutine_handle handle): handle{handle}{} + auto get_handle() { return handle; } + std::coroutine_handle handle; +}; + +class Scheduler { + std::priority_queue>> _prioTasks; + public: + void emplace(int prio, std::coroutine_handle<> task) { + _prioTasks.push(std::make_pair(prio, task)); + } + + void schedule() { + while(!_prioTasks.empty()) { + auto [prio, task] = _prioTasks.top(); + _prioTasks.pop(); + task.resume(); + + if(!task.done()) { + _prioTasks.push(std::make_pair(prio, task)); + } + else { + task.destroy(); + } + } + } + +}; + + +Task createTask(const std::string& name) { + std::cout << name << " start\n"; + co_await std::suspend_always(); + std::cout << name << " execute\n"; + co_await std::suspend_always(); + std::cout << name << " finish\n"; +} + + +int main() { + Scheduler scheduler1; + scheduler1.emplace(0, createTask("TaskA").get_handle()); + scheduler1.emplace(1, createTask(" TaskB").get_handle()); + scheduler1.schedule(); + Scheduler scheduler2; + scheduler2.emplace(1, createTask("TaskA").get_handle()); + scheduler2.emplace(0, createTask(" TaskB").get_handle()); + scheduler2.schedule(); +} +``` + + +## 开源项目介绍 + +- [asteria](https://github.com/lhmouse/asteria) 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线 + +最近进展? + +- [Unilang](https://github.com/linuxdeepin/unilang) deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了 + +- https://gitee.com/okstar-org/ok-edu-desktop 一个IM通信软件,做IM的可以关注,现在正在做全面整合阶段,开始组建商业团队阶段,年底开始融资,你参加了就快发财了,会的快来 + +- https://github.com/hanickadot/cthash 编译期sha算法 + + + + +? +