layout | title |
---|---|
post |
第85期 |
从reddit/hackernews/lobsters/meetingcpp/purecpp知乎/等等摘抄一些c++动态
欢迎投稿,推荐或自荐文章/软件/资源等
公众号也有了
不过没有留言功能
可以贴在下一期草稿里 草稿链接
2022 1021
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-10-19 第172期
2022全球C++及系统软件技术大会演讲嘉宾PPT集合: https://city.boolan.com/2022_CPPSummit.pdf
2020年的在这里 https://city.boolan.com/2020CPP.pdf
页数很多。没有视频。走马观花随便看看
2022 10.23 purecpp C++大会直播 链接 http://t.csdn.cn/uBRwn
直播内容
基础概念
当我们有一个带GC的编程语言runtime的时候,这个GC该什么时候进行垃圾回收?一般来说,一个runtime会有一个heap limit(L),当程序消耗内存量达到limit后,则会进行垃圾回收,使得内存使用量下降到limit以下。假设程序自己的live set size(无法被GC清掉的,还在用着的内存)是S, 那一般来说,会设置成L = N * S,其中N是一个2之类的常数。这代表着,一个带GC的程序的最大内存使用量,应该是手动内存管理的内存使用量的两倍。但,这其实并不合理!我们在paper里面对垃圾回收进行数学建模,然后寻找一个这个问题的最优解。我们最后发现,应该设置成L = S + N * Sqrt(S),就是说 - S越大,我们对应于原先的算法,应该给的内存越小!这时候,我们的算法在v8 javascript engine上可以比原先的GC快30%(同等内存),又或者同等时间下节省15%的内存
我咋感觉和c++里的vector扩容预留空间不能是简单翻倍而是1.5倍 那种场景有点像,也就是说那种大vector的扩容分配空间可以用这种算法再优化一波
再比如各种buffer pool 管理策略,内存都是钉死的,怎么找到最佳的S呢?
有点意思
给你一个整体的视角,从流水线到cache到虚拟内存 。看图可以点这个
讲SEH的。
__try
{
Block1;
}
__except (FilterExpression)
{
Block2;
}
__finally
{
Block3;
}
乍一看很常规是不是,你再仔细看看有没有遗漏?
FilterExpression有可能异常!如果FilterExpression异常,它是被外层的try包起来的,也就是说,会继续走到__except,会匹配到FilterExpression,会继续异常
最终堆栈溢出程序挂掉
一般遇不到,遇到就会很莫名其妙
之前也聊过,CTAD可能有害,所以要加上告警规避这种场景,但是简单的告警还有可能漏掉某些场景,建议直接-Werror=ctad
vector在move场景是比较保守的,如果T本身不是noexcept move,就copy。本身也是怕T本身move的副作用引发失败,退而求其次保守copy
考虑一个T实现
struct Widget {
std::list<int> m_ = std::list<int>(1000);
// MSVC's std::list isn't nothrow movable
};
std::vector<Widget> v(10);
try {
v.reserve(v.capacity()+1); // reallocate the buffer
} catch (...) {
// is v still in its old state?
}
正常的场景,不在乎copy的代价,只要保证Widget没问题就行,强异常处理bad alloc。这样能用没啥问题
如果强异常场景,还要尽可能的move,m_的move可能会有问题,那只好给Widget一个noexcept的move
struct Widget {
std::list<int> m_ = std::list<int>(1000);
// MSVC's std::list isn't nothrow movable
explicit Widget() = default;
Widget(Widget&&) noexcept = default; // !!
Widget(const Widget&) = default;
Widget& operator=(Widget&&) = default;
Widget& operator=(const Widget&) = default;
};
std::vector<Widget> v(10);
又想尽可能的move,又想处理bad alloc,其他异常无所谓,做不到,只能自己造一个std::vector了
这个就是作者讨论的类似CAP的那种三角问题
说实话我没怎么理解明白
使用核心内建的功能,而不是库提供的功能
比如 alignof 好过 std::alignment_of_v
static_assert(std::alignment_of_v<Widget> == 8); // worse
static_assert(alignof(Widget) == 8); // better
比如alignas好过 std::aligned_storage_t
std::aligned_storage<sizeof(Widget)> data; // utterly wrong
std::aligned_storage_t<sizeof(Widget)> data; // still kind of wrong
std::aligned_storage_t<sizeof(Widget), alignof(Widget)> data; // correct but bad
alignas(Widget) char data[sizeof(Widget)]; // correct and better
比如char好过std::bytes
std::byte data[100]; // worse
char data[100]; // better
int data[10];
// worse
void mycopy(std::byte *dst, const std::byte *src, size_t n);
mycopy((std::byte*)data, (std::byte*)(data+5), 5 * sizeof(int));
// better
void mycopy(void *dst, const void *src, size_t n);
mycopy(data, data+5, 5 * sizeof(int));
lambda 好过bind
range for好过std::for_each
不列代码了
struct好过tuple有名字信息
placement new 好过construct_at
alignas(Widget) char data[sizeof(Widget)];
Widget *pw = std::construct_at((Widget*)data, x, y); // worse
Widget *pw = ::new ((void*)data) Widget(x, y); // better
当然这些都是习惯。不强求
依赖计算越长,CPU pipeline越差
为啥unique_ptr构造函数不把make_unique的活给干了??语义不清晰。T里的构造很让人困惑
#include <bitset>
constexpr std::bitset<4> b1{"0011"};
static_assert(0b0011 == b1.to_ulong());
constexpr std::bitset<4> b2{0b0011};
static_assert(b1 == b2);
这玩意谁用啊。folly有个省空间的bitset
signum是个很常规的函数
#include <cmath>
float signum_safe(float Value) {
if( Value < 0.0 )
return -1.0;
if( Value > 0.0 )
return 1.0;
if( std::isnan(Value) )
return Value;
return 0.0;
}
文章讨论用avx512 vfixupimm来实现,并且如何妥善的处理isnan?
直接看代码吧 https://compiler-explorer.com/z/ee8MGrrEY
bind的一种强化
cppcon视频开始放流了,一天一个基本上
讨论值语义的。没能看完
阿里许传奇讲他们应用编译优化的一些经验,LTO, 编译cache,module之类的。没看完。这个英语有点难受。我估计会有中文版的
给我整困了
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群753302367和作者对线
- snatch 又一个test框架 c++20
- mGBA 0.10.0 gba模拟器
- ezpz 一个parser框架