-
引入协程背景有大量的异步业务逻辑, 传统的回调代码割裂, 可读性差, 不可避免的回调地狱简化编码复杂度,希望底层能够支持协程, 简化跨线程或者实现rpc的能力项目Github: CrystalNetCrystalNet支持C++20, 包括requires, 协程等特性协程框架是CrystalNet的一个底层支持协程源码路径:kernel/include/kernel/comp/Coroutines测试case: TestCoroutine.h/TestCoroutine.cpp TestPoller.h/TestPoller.cpp细节介绍封装一个通用的协程类template<typename T> class CoTask<T>封装一个阻塞等待类CoWaiter,并提供阻塞等待接口:CoTask<> Waiting(), 用于等待条件满足时唤醒协程设计封装了一个Poller,主要用于处理事件循环, 协程的suspend时候会向Poller抛异步任务调度协程, 直到在CoWaiting时永久阻塞CoTask提供GetParam让用户在协程阻塞时获取到协程句柄,方便用户在条件满足时通过协程句柄唤醒协程Poller提供SendAsync接口实现跨线程的通信(协程方式提供)// 跨线程协程消息(otherPoller也可以是自己) // req暂时只能传指针,而且会在otherChannel(可能不同线程)释放 // req/res 必须实现Release, ToString接口 template<typename ResType, typename ReqType> requires requires(ReqType req, ResType res) { // req/res必须有Release接口 req.Release(); res.Release(); // req/res必须有ToString接口 req.ToString(); res.ToString(); } CoTask<KERNEL_NS::SmartPtr<ResType, AutoDelMethods::Release>> SendToAsync(Poller &otherPoller, ReqType *req) { // 1.ptr用来回传ResType KERNEL_NS::SmartPtr<ResType *, KERNEL_NS::AutoDelMethods::CustomDelete> ptr(KERNEL_NS::KernelCastTo<ResType *>( kernel::KernelAllocMemory<KERNEL_NS::_Build::TL>(sizeof(ResType **)))); ptr.SetClosureDelegate([](void *p) { // 释放packet auto castP = KERNEL_NS::KernelCastTo<ResType*>(p); if(*castP) (*castP)->Release(); KERNEL_NS::KernelFreeMemory<KERNEL_NS::_Build::TL>(castP); }); *ptr = NULL; // 设置stub => ResType的事件回调 UInt64 stub = ++_maxStub; KERNEL_NS::SmartPtr<KERNEL_NS::TaskParamRefWrapper, KERNEL_NS::AutoDelMethods::Release> params = KERNEL_NS::TaskParamRefWrapper::NewThreadLocal_TaskParamRefWrapper(); SubscribeStubEvent(stub, [ptr, params](KERNEL_NS::StubPollerEvent *ev) mutable { KERNEL_NS::ObjectPollerEvent<ResType> *finalEv = KernelCastTo<KERNEL_NS::ObjectPollerEvent<ResType>>(ev); // 将结果带出去 *ptr = finalEv->_obj; finalEv->_obj = NULL; // 唤醒Waiter auto &coParam = params->_params; if(coParam && coParam->_handle) coParam->_handle->ForceAwake(); }); // 发送对象事件 ObjectPollerEvent到 other auto iterChannel = _targetPollerRefChannel.find(&otherPoller); if(LIKELY(iterChannel != _targetPollerRefChannel.end())) { auto objEvent = ObjectPollerEvent<ReqType>::New_ObjectPollerEvent(stub, false, this, iterChannel->second); objEvent->_obj = req; iterChannel->second->Send(objEvent); } else { auto objEvent = ObjectPollerEvent<ReqType>::New_ObjectPollerEvent(stub, false, this, nullptr); objEvent->_obj = req; otherPoller.Push(objEvent); } // 等待 ObjectPollerEvent 的返回消息唤醒 auto poller = this; // 外部如果协程销毁兜底销毁资源 auto releaseFun = [stub, poller]() { poller->UnSubscribeStubEvent(stub); }; auto delg = KERNEL_CREATE_CLOSURE_DELEGATE(releaseFun, void); co_await KERNEL_NS::Waiting().SetDisableSuspend().GetParam(params).SetRelease(delg); if(LIKELY(params->_params)) { auto &pa = params->_params; if(pa->_errCode != Status::Success) { g_Log->Warn(LOGFMT_OBJ_TAG("waiting err:%d, stub:%llu, req:%p") , pa->_errCode, stub, req); UnSubscribeStubEvent(stub); } // 销毁waiting协程 if(pa->_handle) pa->_handle->DestroyHandle(pa->_errCode); } // 3.将消息回调中的ResType引用设置成空 auto res = *ptr; *ptr = NULL; co_return KERNEL_NS::SmartPtr<ResType, KERNEL_NS::AutoDelMethods::Release>(res); } 提供异步化工具函数: PostCaller异步编码举例代码在测试用例:TestPoller, 示例中实现了co_await 请求一个req,并返回一个resclass TestTimeoutStartup : public KERNEL_NS::IThreadStartUp { POOL_CREATE_OBJ_DEFAULT_P1(IThreadStartUp, TestTimeoutStartup); public: TestTimeoutStartup(KERNEL_NS::LibEventLoopThread * target) : _target(target) { } virtual void Run() override { KERNEL_NS::PostCaller([this]() mutable -> KERNEL_NS::CoTask<> { auto targetPoller = co_await _target->GetPoller(); auto req = HelloWorldReq::New_HelloWorldReq(); auto res = co_await targetPoller->template SendAsync<HelloWorldRes, HelloWorldReq>(req).SetTimeout(KERNEL_NS::TimeSlice::FromSeconds(5)); g_Log->Info(LOGFMT_NON_OBJ_TAG(TestTimeoutStartup, "res return")); }); } virtual void Release() override { TestTimeoutStartup::Delete_TestTimeoutStartup(this); } KERNEL_NS::LibEventLoopThread * _target; };
-
缓存是提升系统性能的核心机制之一,通过减少重复计算或数据访问来优化响应速度。以下是三种常见缓存淘汰策略的核心原理与适用场景的深度分析:1. LRU Cache(最近最少使用缓存)核心原理淘汰策略:当缓存空间不足时,优先淘汰最近最少使用的数据项。实现方式:通常通过双向链表+哈希表实现:链表按访问时间排序(最新访问的项移动到链表头部)。哈希表存储键值对,支持O(1)时间复杂度的查找。适用场景:热点数据集中:如用户访问的热门文章、商品推荐等,数据访问存在局部性原理(即近期访问的数据更可能被再次访问)。内存敏感型系统:需要严格控制缓存占用,例如嵌入式设备、内存受限的微服务。缓存大小动态变化:无需预先设定数据优先级,完全由访问模式决定。示例浏览器缓存:用户最近浏览的网页会被优先保留。Redis的maxmemory-policy:可通过volatile-lru或allkeys-lru策略实现。数据库查询缓存:高频SQL查询结果会被保留。2. TTL Cache(带过期时间的缓存)核心原理淘汰策略:每个缓存项设置生存时间(TTL),到期后自动失效,无论是否被访问。实现方式:每个缓存项附加一个时间戳或定时器。定期扫描或惰性删除(访问时检查是否过期)。适用场景:临时性数据:如验证码、一次性令牌、会话数据(需严格时效性)。避免数据不一致:当底层数据可能被外部修改时(如第三方API响应、爬虫数据)。防缓存雪崩:通过随机化TTL(如10-20分钟),避免大量缓存同时过期。示例Session存储:用户登录后生成的Token通常设置30分钟TTL。验证码服务:短信验证码的有效期(如5分钟)。实时数据缓存:股票行情、天气数据等需定期刷新的场景。3. LFU Cache(最不频繁使用缓存)核心原理淘汰策略:当缓存空间不足时,优先淘汰访问频率最低的数据项。实现方式:为每个缓存项维护一个访问计数器。淘汰时选择计数器最小的项(或结合LRU,淘汰访问次数最少且最久未使用的项)。适用场景:访问模式稳定:数据访问频率差异显著,但无明显的局部性(如某些配置项、静态资源)。长尾效应明显:少数高频数据占用了大部分访问,但仍有大量低频数据需要缓存。避免缓存污染:防止偶然的热点数据长期占用缓存(如突发流量导致的短期热点)。示例CDN内容分发:某些冷门视频偶尔被大量用户点击后,仍可能因低频访问被淘汰。推荐系统:用户兴趣可能随时间变化,低频兴趣项会被优先淘汰。Redis的volatile-lfu/allkeys-lfu:Redis 4.0+支持的LFU策略。策略对比与选择建议策略核心指标优势劣势典型场景LRU访问时间实现简单,适合热点数据无法处理访问频率差异大的数据用户行为分析、热点文章推荐TTL生存时间强制数据过期,避免脏数据无法利用访问模式优化缓存利用率验证码、会话、实时数据LFU访问频率适合访问模式稳定的场景无法应对访问频率的短期变化CDN内容、配置项、推荐系统混合策略与扩展LRU-K:结合访问次数与时间(如LRU-2要求数据被访问2次才进入缓存)。Two-Queue(2Q):维护两个LRU队列,分别处理新数据和老数据。W-TinyLFU:结合LFU的访问计数与Bloom Filter的近似统计,适用于分布式缓存(如Caffeine库)。实际应用中的注意事项缓存穿透:对不存在的键也设置空值缓存(带TTL),避免大量请求穿透到数据库。缓存击穿:对热点数据设置永久缓存+后台刷新,或使用互斥锁保护缓存重建。缓存雪崩:通过随机化TTL或多级缓存(如本地缓存+分布式缓存)分散过期时间。总结LRU:适合访问模式集中的场景(如用户近期行为)。TTL:适合临时性或外部依赖数据(如验证码、API响应)。LFU:适合访问频率差异大但模式稳定的场景(如CDN内容)。根据业务特点选择合适的策略,或结合多种策略(如Redis的volatile-lfu+maxmemory-policy)实现更高效的缓存管理。
-
unexpected_eoln错误什么意思,自己运行是对的,传上去报错
-
调优思路 性能优化的思路如下: 如果CPU的利用率不高,说明资源没有充分利用,可以通过工具(如strace)查看应用程序阻塞在哪里,一般为磁盘,网络或应用程序自己的业务逻辑有休眠或信号等待,这些优化措施在其它章节描述。 如果CPU利用率高,可以选择更好的硬件,优化硬件的配置参数来适配业务场景,或者通过优化软件来降低CPU占用率。 根据CPU的能力配置合适的内存条,建议内存满通道配置,发挥内存最大带宽:一颗鲲鹏920处理器的内存通道数为8,两颗鲲鹏920处理器的内存通道数为16;建议选择高频率的内存条,提升内存带宽:鲲鹏920在1DPC配置时,支持的内存最高频率为3200MHz。 介绍 top是最常用的Linux性能监测工具之一。通过top工具可以监视进程和系统整体性能。 命令参考举例: 命令 说明 top 查看系统整体的CPU、内存资源消耗。 top执行后输入1 查看每个CPU core资源使用情况。 top执行后输入F,并选择P选项 查看线程执行过程中是否调度到其它CPU core。 top -p $PID -H 查看某个进程内所有线程的CPU资源占用。 安装方式 系统自带,无需安装。 使用方法 使用top命令统计整体CPU、内存资源消耗。 CPU项:显示当前总的CPU时间使用分布。 us表示用户态程序占用的CPU时间百分比。 sy表示 内核态 程序所占用的CPU时间百分比。 wa表示等待IO等待占用的CPU时间百分比。 hi表示硬中断所占用的CPU时间百分比。 si表示软中断所占用的CPU时间百分比。 通过这些参数我们可以分析CPU时间的分布,是否有较多的IO等待。在执行完调优步骤后,我们也可以对CPU使用时间进行前后对比。如果在运行相同程序、业务情况下CPU使用时间降低,说明性能有提升。 KiB Mem:表示服务器的总内存大小以及使用情况。 KiB Swap:表示当前所使用的Swap空间的大小。Swap空间即当内存不足的时候,把一部分硬盘空间虚拟成内存使用。如果当前所使用的Swap空间大于0,可以考虑优化应用的内存占用或增加物理内存。 在top命令执行后按1,查看每个CPU core的使用情况。 通过该命令可以查看单个CPU core的使用情况,如果CPU占用集中在某几个CPU core上,可以结合业务分析触发原因,从而找到优化思路。 选中top命令的P选项,查看线程运行在哪些CPU core上。 在top命令执行后按F,可以进入top命令管理界面。在该界面通过上下键移动光标到P选项,通过空格键选中后按Esc退出,即可显示出线程运行的CPU核。观察一段时间,若业务线程在不同NUMA节点内的CPU core上运行,则说明存在较多的跨NUMA访问,可通过NUMA绑核进行优化。 使用top -p $PID -H命令观察进程中每个线程的CPU资源使用。 “-p”后接的参数为待观察的进程ID。通过该命令可以找出消耗资源多的线程,随后可根据线程号分析线程中的热点函数、调用过程等情况。 三、介绍 Perf工具是非常强大的Linux性能分析工具,可以通过该工具获得进程内的调用情况、资源消耗情况并查找分析热点函数。 命令参考举例: 命令 说明 perf top 查看当前系统中的热点函数。 perf sched record – sleep 1 -p $PID 记录进程在1s内的系统调用。 perf sched latency --sort max 查看上一步记录的结果,以调度延迟排序。 安装方式 以CentOS为例,使用如下命令安装: yum -y install perf 使用方法 通过perf top命令查找热点函数。 该命令统计各个函数在某个性能事件上的热度,默认显示CPU占用率,可以通过“-e”监控其它事件。 Overhead表示当前事件在全部事件中占的比例。 Shared Object表示当前事件生产者,如kernel、perf命令、C语言库函数等。 Symbol则表示热点事件对应的函数名称。 通过热点函数,我们可以找到消耗资源较多的行为,从而有针对性的进行优化。 收集一段时间内的线程调用。 perf sched record命令用于记录一段时间内,进程的调用情况。“-p”后接进程号,“sleep”后接统计时长,单位为秒。收集到的信息自动存放在当前目录下,文件名为perf.data。 解析收集到的线程调度信息。 perf sched latency命令可以解析当前目录下的perf.data文件。“-s”表示进行排序,后接参数“max”表示按照最大延迟时间大小排序。 四、优化方法: 原理 局部性原理分为时间局部性原理和空间局部性原理: 时间局部性原理(temporal locality):如果某个数据项被访问,那么在不久的将来它可能再次被访问。 空间局部性原理(spatial locality):如果某个数据项被访问,那么与其地址相邻的数据项可能很快也会被访问。 CPU将内存中的数据读到CPU的高速缓冲Cache时,会根据局部性原理,除了读取本次要访问的数据,还会预取本次数据的周边数据到Cache里面,如果预取的数据是下次要访问的数据,那么性能会提升,如果预取的数据不是下次要取的数据,那么会浪费内存带宽。 对于数据比较集中的场景,预取的命中率高,适合打开CPU预取,反之需要关闭CPU预取。目前发现speccpu和X265软件场景适合打开CPU预取,STREAM测试工具、Nginx和数据库场景需要关闭CPU预取。 修改方式 按照进入BIOS界面的步骤进入 BIOS ,然后在BIOS的如下位置设置CPU的预取开关。
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签