前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 中文周刊 第106期

C++ 中文周刊 第106期

作者头像
王很水
发布2023-03-25 14:08:34
3340
发布2023-03-25 14:08:34
举报

C++ 中文周刊 第106期


资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2023-03-22 第194期

AMD EPYC Genoa-X CPU 曝光:配备 1.25GB 缓存,预计将于年内推出

3D Vcache服务器,1G多cache,离谱,zen3就很省钱,zen4这波又得扩大一波市场占用率,英特尔慌不慌

文章

代码语言:javascript
复制
class parse {
public:
  parse(std::string str) : str_(str) {}

  template<typename T>
  operator T() && {
    if constexpr (std::is_integral_v<T>) {
      T t = atoi(str_.data());
      return t;
    }
    else {
      return str_;
    }
  }

private:
  std::string str_;
};

std::string str = "42";
int i = parse(str);
assert(i == 42);

std::string s = parse(str);
assert(s == "42");

有趣

代码语言:javascript
复制
enum class error { runtime_error };

[[nodiscard]] auto foo() -> std::expected<int, error> {
    return std::unexpected(error::runtime_error);
}

int main() {
    const auto e = foo();
    e.and_then([](const auto& e) -> std::expected<int, error> {
         std::cout << int(e);  // not printed
         return {};
     }).or_else([](const auto& e) -> std::expected<int, error> {
        std::cout << int(e);  // prints 0
        return {};
    });
}

真不容易,之前就该有的东西

省流,替换unordered_map为tsl/robin_map.h,性能提升明显(2023了大家应该都知道标准库这个map垃圾了)

省流: 空基类优化

苹果M1平台下的perf counter https://gist.github.com/ibireme/173517c208c7dc333ba962c1f0d67d12

例子

代码语言:javascript
复制
#include "performancecounters/event_counter.h"

event_collector collector;

void f() {
  event_aggregate aggregate{};
  for (size_t i = 0; i < repeat; i++) {
   collector.start();
   function(); // benchmark this function
   event_count allocate_count = collector.end();
   aggregate << allocate_count;
  }
}

快一点,但不多,一般来说热点也不在这

监控服务,发现性能瓶颈,但发现监控服务本身成了瓶颈,修复监控服务的bug,有意思

看不懂,但感觉有点意思

实现了个限流桶算法。看个乐,直接贴了

https://github.com/mvorbrodt/blog/blob/master/src/token_bucket.hpp

代码语言:javascript
复制
#include <atomic>
#include <chrono>
#include <thread>
#include <stdexcept>
 
// Multi-Threaded Version of Token Bucket
class token_bucket_mt {
public:
	using clock = std::chrono::steady_clock;
	using duration = clock::duration;
	using time_point = clock::time_point;
 
	using atomic_duration = std::atomic<duration>;
	using atomic_time_point = std::atomic<time_point>;
 
	token_bucket_mt(std::size_t tokens_per_second, std::size_t token_capacity, bool full = true)
	: token_bucket_mt(std::chrono::duration_cast<duration>(std::chrono::seconds(1)) / tokens_per_second, token_capacity, full) {}
 
	token_bucket_mt(duration time_per_token, std::size_t token_capacity, bool full = true)
	: m_time{ full ? time_point{} : clock::now() }, m_time_per_token{ time_per_token }, m_time_per_burst{ time_per_token * token_capacity }
	{
		if (time_per_token.count() <= 0) throw std::invalid_argument("Invalid token rate!");
		if (!token_capacity) throw std::invalid_argument("Invalid token capacity!");
	}
 
	token_bucket_mt(const token_bucket_mt& other) noexcept
	: m_time{ other.m_time.load() },
	m_time_per_token{ other.m_time_per_token.load() },
	m_time_per_burst{ other.m_time_per_burst.load() } {}
 
	token_bucket_mt& operator = (const token_bucket_mt& other) noexcept {
		m_time = other.m_time.load();
		m_time_per_token = other.m_time_per_token.load();
		m_time_per_burst = other.m_time_per_burst.load();
		return *this;
	}
 
	void set_rate(std::size_t tokens_per_second) {
		set_rate(std::chrono::duration_cast<duration>(std::chrono::seconds(1)) / tokens_per_second);
	}
 
	void set_rate(duration time_per_token) {
		if (time_per_token.count() <= 0) throw std::invalid_argument("Invalid token rate!");
		m_time_per_token = time_per_token;
	}
 
	void set_capacity(std::size_t token_capacity) {
		if (!token_capacity) throw std::invalid_argument("Invalid token capacity!");
		m_time_per_burst = m_time_per_token.load() * token_capacity;
	}
 
	void drain() noexcept {
		m_time = clock::now();
	}
 
	void refill() noexcept {
		auto now = clock::now();
		m_time = now - m_time_per_burst.load();
	}
 
	[[nodiscard]] bool try_consume(std::size_t tokens = 1, duration* time_needed = nullptr) noexcept {
		auto now = clock::now();
		auto delay = tokens * m_time_per_token.load(std::memory_order_relaxed);
		auto min_time = now - m_time_per_burst.load(std::memory_order_relaxed);
		auto old_time = m_time.load(std::memory_order_relaxed);
		auto new_time = min_time > old_time ? min_time : old_time;
 
		while (true) {
			new_time += delay;
			if (new_time > now) {
				if (time_needed != nullptr)
					*time_needed = new_time - now;
 
				return false;
			}
 
			if (m_time.compare_exchange_weak(old_time, new_time, std::memory_order_relaxed, std::memory_order_relaxed))
				return true;
 
			new_time = old_time;
		}
	}
 
	void consume(std::size_t tokens = 1) noexcept {
		while (!try_consume(tokens))
			std::this_thread::yield();
	}
 
	void wait(std::size_t tokens = 1) noexcept {
		duration time_needed;
		while (!try_consume(tokens, &time_needed))
			std::this_thread::sleep_for(time_needed);
	}
 
private:
	atomic_time_point m_time;
	atomic_duration m_time_per_token;
	atomic_duration m_time_per_burst;
};
 
// Default Token Bucket
using token_bucket = token_bucket_mt;
代码语言:javascript
复制
#include <iostream>
#include <iomanip>
#include <vector>
#include <latch>
#include "token_bucket.hpp"
 
#define all(c) for(auto& it : c) it
 
int main() {
	using namespace std;
	using namespace std::chrono;
 
	try {
		auto N = 1;
		auto bucket = token_bucket(1ms, 1000, true);
		auto count = thread::hardware_concurrency() - 1;
		auto run = atomic_bool{ true };
		auto total = atomic_uint64_t{};
		auto counts = vector<atomic_uint64_t>(count);
		auto fair_start = latch(count + 2);
		auto threads = vector<thread>(count);
 
		thread([&] {
			fair_start.arrive_and_wait();
 
			auto start = steady_clock::now();
			auto sec = 0;
 
			while (run)
			{
				auto cnt = 1;
				for (auto& count : counts)
					cout << fixed << "Cnt " << cnt++ << ":\t" << count << "\t / \t" << (100.0 * count / total) << " % \n";
 
				cout << "Total:\t" << total << "\nTime:\t" << duration_cast<seconds>(steady_clock::now() - start).count() << "s\n" << endl;
 
				this_thread::sleep_until(start + seconds(++sec));
			}
		}).detach();
 
		auto worker = [&](auto x) {
			fair_start.arrive_and_wait();
 
			while (run) {
				bucket.consume(N);
				total += N;
				counts[x] += N;
			}
		};
 
		thread([&] {
			bucket.drain();
 
			fair_start.arrive_and_wait();
 
			this_thread::sleep_for(3s);
 
			bucket.set_rate(1s);
			bucket.set_capacity(1000000);
 
			this_thread::sleep_for(3s);
 
			bucket.refill();
		}).detach();
 
		all(threads) = thread(worker, --count);
 
		cin.get();
		run = false;
		all(threads).join();
	} catch (exception& ex) {
		cerr << ex.what() << endl;
	}
}

视频

看代码

代码语言:javascript
复制
#include <list>
#include <vector>

template <template <typename T, typename Alloc = std::allocator<T>>
          class Container>
[[nodiscard]] constexpr auto transform_into(auto f, const auto &input) noexcept(
    noexcept(f(input.front())))
  requires requires { f(input.front()); }
{
  Container<decltype(f(input.front()))> retval;
  retval.reserve(input.size());

  for (auto &&value : input) {
    retval.push_back(f(value));
  }

  return retval;
}

int main() {
  std::list<int> data{1, 2, 3, 4};

  const auto result =
      transform_into<std::vector>([](const auto i) { return i * 1.1; }, data);

  static_assert(std::is_same_v<decltype(result)::value_type, double>);
}

只能说,这个例子不配这种级别的抽象

  • std::function: a deep dive behind the curtain - Andreas Reischuck - Meeting C++ 2022 开源项目需要人手
  • asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
  • pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
  • Unilang deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
  • paozhu 国人开发的web库,和drogon联系过没共建而考虑自己的需求基于asio开发。感兴趣的可以体验一下,挂在这里长期推荐了

新项目介绍/版本更新


看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢!

本文永久链接

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • C++ 中文周刊 第106期
    • 资讯
      • 文章
        • 视频
          • 新项目介绍/版本更新
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档