公众号
qq群 点击进入
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
欢迎投稿,推荐或自荐文章/软件/资源等
请提交 issue 或评论区留言
本期文章由 黄亮Anthony HNY 不语 赞助
祝大家新年快乐
把from_chars搬到c++11,我建议放弃c++11 ,2024了bro 文档
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-01-31 第239期
What’s New in vcpkg January 2024
另外有个重写loki的活动哈,有点幽默,感兴趣可以点击直达
(重写loki不是已经做了吗,folly啊)
brpc发布1.8版本 release note
redis 为啥不用?避免影响rdb生成?
另外这有个 hugetop命令
代码这里 https://gitlab.com/procps-ng/procps
群友翻译,非常干货,值得看看
不过异常设计的还是太傻呗了
之前聊到的MLIR 在c/c++上的落地 CIR准备合入到LLVM
感觉clang明显更激进一些,而gcc还是一群老登
傻逼locale问题,虽然你是静态连接libstdcxx-static,但是locale并不static
errno是内核设置还是libc设置?当然是libc
怎么验证? 简单来说就是同一个系统调用,调用syscall/通过汇编调用,观察errno变化
static int use_wrapper(int cmd, union bpf_attr *attr, unsigned int size) {
long ret;
errno = 0;
ret = syscall(__NR_bpf, cmd, attr, size);
if (ret < 0)
printf("wrapped syscall failed, ret=%d, errno=%d\n", ret, errno);
else
printf("wrapped syscall succeeded\n");
}
asm
static int use_raw(int cmd, union bpf_attr *attr, unsigned int size) {
long ret;
errno = 0;
__asm__(
"movq %1, %%rax\n" /* syscall number */
"movq %2, %%rdi\n" /* arg1 */
"movq %3, %%rsi\n" /* arg2 */
"movq %4, %%rdx\n" /* arg3 */
"syscall\n"
"movq %%rax, %0\n"
/* retval */
: "=r"(ret)
/* input operands */
: "r"((long)__NR_bpf), "r"((long)cmd), "r"((long)attr), "r"((long)size)
/* clobbers */
: "rax", "rdi", "rsi", "rdx"
);
/* Check return value */
if (ret < 0)
printf("raw syscall failed, ret=%d, errno=%d\n", ret, errno);
else
printf("raw syscall succeeded\n");
}
template <typename T1, typename T2>
struct Bar {
Bar(T1, T2) { }
};
int main() {
auto x = Bar(1, 2);
auto y = new Bar(3, 4);
auto z = new Bar{3, 4};
}
低版本的gcc (现在低版本gcc指的是7/8了)用大括号绕过即可,为什么列这个呢,因为我遇到了
https://github.com/ibogosavljevic/johnysswlab/blob/master/2023-12-branches-memory/binary_search.cpp#L53
int binary_search(int* array, int number_of_elements, int key) {
int low = 0, high = number_of_elements-1, mid;
while(low <= high) {
mid = (low + high)/2;
if (st == search_type::REGULAR) {
if(array[mid] < key)
low = mid + 1;
else if(array[mid] == key)
return mid;
else
high = mid-1;
}
if (st == search_type::CONDITIONAL_MOVE) {
int middle = array[mid];
if (middle == key) {
return mid;
}
int new_low = mid + 1;
int new_high = mid - 1;
__asm__ (
"cmp %[array_middle], %[key];"
"cmovae %[new_low], %[low];"
"cmovb %[new_high], %[high];"
: [low] "+&r"(low), [high] "+&r"(high)
: [new_low] "g"(new_low), [new_high] "g"(new_high), [array_middle] "g"(middle), [key] "g"(key)
: "cc"
);
}
if (st == search_type::ARITHMETIC) {
int middle = array[mid];
if (middle == key) {
return mid;
}
int new_low = mid + 1;
int new_high = mid - 1;
int condition = array[mid] < key;
int condition_true_mask = -condition;
int condition_false_mask = -(1 - condition);
low += condition_true_mask & (new_low - low);
high += condition_false_mask & (new_high - high);
}
}
return -1;
}
Array Size (in elements) | Original | Conditional Moves | Arithmetics |
---|---|---|---|
4 K | Runtime: 0.22 sInstr: 434 M CPI: 1.96Mem. Data Volume: 0.45 GB | Runtime: 0.14 sInstr: 785 MCPI: 0.728Mem. Data Volume: 0.25 GB | Runtime: 0.19 sInstr: 1.102 MCPI: 0.69Mem. Data Volume: 0.32 GB |
16 K | Runtime: 0.26 sInstr: 511 MCPI: 2.01Mem. Data Volume: 0.49 GB | Runtime: 0.19 sInstr: 928 MCPI: 0.77Mem. Data Volume: 0.39 GB | Runtime: 0.24 sInstr: 1.308 MCPI: 0.72Mem. Data Volume: 0.46 GB |
64 K | Runtime: 0.32 sInstr: 584 MCPI: 2.143Mem. Data Volume: 0.48 GB | Runtime: 0.24 sInstr: 1.064 MCPI: 0.90Mem. Data Volume: 0.25 GB | Runtime: 0.31Instr: 1.504CPI: 0.82Mem. Data Volume: 0.26 GB |
256 K | Runtime: 0.43 sInstr: 646 MCPI: 2.59Mem. Data Volume: 0.36 GB | Runtime: 0.39 sInstr: 1.199 MCPI: 1.28Mem. Data Volume: 0.32 GB | Runtime: 0.47 sInstr: 1.698 MCPI: 1.09Mem. Data Volume: 0.36 GB |
1 M | Runtime: 0.56 sInstr: 727 MCPI: 3.05Mem. Data Volume: 0.67 GB | Runtime: 0.59 sInstr: 1.333 MCPI: 1.72Mem. Data Volume: 0.59 GB | Runtime: 0.70 sInstr: 1.891 MCPI: 1.42Mem. Data Volume: 0.68 GB |
4 M | Runtime: 1.127 sInstr: 798 MCPI: 4.65Mem. Data Volume: 9.94 GB | Runtime: 1.48 sInstr: 1.467 MCPI: 3.1Mem. Data Volume: 3.75 GB | Runtime: 1.59 sInstr: 2.084 MCPI: 2.45Mem. Data Volume: 3.9 GB |
16 M | Runtime: 1.65 sInstr: 870 MCPI: 6.26Mem. Data Volume: 18.48 GB | Runtime: 2.75 sInstr: 1.601CPI: 4.16Mem. Data Volume: 6.95 GB | Runtime: 2.90 sInstr: 2.277 MCPI: 3.18Mem. Data Volume: 7.05 GB |
课外阅读
快排代码
static int partition(std::vector<float>& vector, int low, int high) {
float pivot = vector[high];
int i = (low - 1);
for (int j = low; j < high; j++) {
if (vector[j] <= pivot) {
i++;
std::swap(vector[i], vector[j]);
}
}
i = i + 1;
std::swap(vector[i], vector[high]);
return i;
}
static int partition(std::vector<float>& vector, int low, int high) {
float* vector_i = &vector[low];
float* vector_j = &vector[low];
float* vector_end = &vector[high];
__m128 pivot = _mm_load_ss(&vector[0] + high);
while(true) {
if (vector_j >= vector_end) break;
__m128 vec_i = _mm_load_ss(vector_i);
__m128 vec_j = _mm_load_ss(vector_j);
__m128 compare = _mm_cmplt_ss(vec_j, pivot); // if (vec_j < pivot)
__m128 new_vec_i = _mm_blendv_ps(vec_i, vec_j, compare);
__m128 new_vec_j = _mm_blendv_ps(vec_j, vec_i, compare);
int increment = _mm_extract_epi32(_mm_castps_si128(compare), 0) & 0x1;
_mm_store_ss(vector_i, new_vec_i);
_mm_store_ss(vector_j, new_vec_j);
vector_i += increment;
vector_j++;
}
std::swap(*vector_i, *vector_end);
return (vector_i - &vector[0]);
}
代码在这里 https://github.com/ibogosavljevic/johnysswlab/blob/master/2022-01-sort/
感觉值得展开讲讲。我找作者要了授权,后面还会继续介绍这个。本地也复现一下
有句讲句 from_chars接口有点难用
auto res = std::from_chars(str.data() + start, str.data() + str.size(), result);
if (res.ec == std::errc{}) {...}
可以用结构化绑定,更好看一点
c++26可以直接这么用
auto res = std::from_chars(str.data() + start, str.data() + str.size(), result);
if (res) { ... }
std::chrono::sys_seconds convertToTimePoint(std::string_view fmtstring)
{
std::chrono::sys_seconds syssec;
std::istringstream in{std::string{raw_data}};//raw_data is a string_view
in >> std::chrono::parse(fmtstring, syssec);
return syssec;
}
没有std::chrono::parse?
std::chrono::sys_seconds convertToTimePoint(std::string_view fmtstring)
{
std::chrono::sys_seconds syssec;
std::istringstream in{std::string{raw_data}};//raw_data is a string_view
std::tm tm = {};
in >> std::get_time(&tm, fmtstring.data());
std::time_t time = std::mktime(&tm);
if(in.good())
syssec = std::chrono::time_point_cast< std::chrono::sys_seconds::duration>(std::chrono::system_clock::from_time_t(time));
else throw std::runtime_error(std::string("Could not convert ") + raw_data + " to a date time value with format string " + fmtstring);
return syssec;
}
有点意思
最近的cppcon有几个不错的都非常硬,我准备单独发,不放在这个环节了,这里预告一下
一个是 taro https://www.bilibili.com/video/BV1BC4y1R7iL/?p=34 这个点子虽然有意思,但是代码完成度一般,感觉不如taskflow
这个可以结合taskflow一起讲一讲。
一个是代码重构
How to Build Your First C++ Automated Refactoring Tool - Kristen Shaker - CppCon 2023
介绍利用clangtidy原地该代码的,自动改,还算有点意思 女演讲人长得有点像三表哥说实话
一个是讲代码分析
Object Introspection: A C++ Memory Profiler - Jonathan Haslam & Aditya Sarwade - CppCon 2023
都是有意思的工作
最近微信群里来了几个做静态检查产品的老哥,突然感觉到国内做对表coverity产品的都没什么声音,这里也和大家一起互动讨论下
都用过哪些静态检查产品?clang-tidy?gconv?coverity?cpplint/cppcheck 感觉基本没啥用,除了修订格式
sonar?
国产的用过吗? analyze 这个听说过吗?
欢迎大家讨论