3步搞定:使用Face Analysis WebUI进行人脸属性识别

核心内容摘要

达沃斯65位元首和首脑齐聚-万祥军| 世界经济论坛·国际科学院组织‍
DAMOYOLO-S模型部署与优化:基于Transformer架构的推理加速技巧

解决Kettle日志中的1900年问题:日志表配置的常见陷阱与优化方案

文章目录事件循环线程事件循环相关源码文件事件主循环机制睡眠钩子Hooks机制睡眠钩子的实现Epoll 实战键盘输入监听事件循环线程众所周知Redis 服务器启动时会开启六个线程Thread-1 [redis-server]主线程Thread-2 [bio_close_file]后台 I/O 线程 - 文件关闭Thread-3 [bio_aof]后台 I/O 线程 - AOF 刷盘Thread-4 [bio_lazy_free]后台 I/O 线程 - 惰性删除Thread-5 [jemalloc_bg_thd]内存整理线程Thread-6 [jemalloc_bg_thd]内存整理线程而事件循环则位于Thread-1 [redis-server]主线程中。

事件循环相关源码文件源码文件说明ae.c事件驱动循环核心ae_epoll.cLinux 系统实现epollae_evport.cSolaris 专用ae_kqueue.cmacOS 专用ae_select.c老旧 Linux 或兼容模式使用ebuckets.c事件桶管理eventnotifier.c事件通讯器事件主循环机制Redis 的事件主循环位于ae.c中核心代码如下voidaeMain(aeEventLoop*eventLoop){eventLoop-stop0;while(!eventLoop-stop){aeProcessEvents(eventLoop,AE_ALL_EVENTS|AE_CALL_BEFORE_SLEEP|AE_CALL_AFTER_SLEEP);}}但死循环非常消耗 CPURedis 是如何让线程进入睡眠等待的呢真正的“睡眠”发生在aeApiPoll中其核心是调用系统epoll_waitstaticintaeApiPoll(aeEventLoop*eventLoop,structtimeval*tvp){aeApiState*stateeventLoop-apidata;intretval,numevents0;retvalepoll_wait(state-epfd,state-events,eventLoop-setsize,tvp?(tvp-tv_sec*1000(tvp-tv_usec

/

:-

;if(retval

{intj;numeventsretval;for(j0;jnumevents;j){intmask0;structepoll_event*estate-eventsj;if(e-eventsEPOLLIN)mask|AE_READABLE;if(e-eventsEPOLLOUT)mask|AE_WRITABLE;if(e-eventsEPOLLERR)mask|AE_WRITABLE|AE_READABLE;if(e-eventsEPOLLHUP)mask|AE_WRITABLE|AE_READABLE;eventLoop-fired[j].fde-data.fd;eventLoop-fired[j].maskmask;}}elseif(retval-1errno!EINTR){panic(aeApiPoll: epoll_wait, %s,strerror(errno));}returnnumevents;}epoll_wait就是实现“睡眠”的系统调用。

当没有事件时线程在此阻塞不消耗 CPU。

睡眠钩子Hooks机制为了在睡眠前后执行必要逻辑Redis 提供了钩子函数。

在initServer函数中注册aeSetBeforeSleepProc(server.el, beforeSleep); aeSetAfterSleepProc(server.el, afterSleep);在aeProcessEvents中调用if (eventLoop-beforesleep ! NULL (flags AE_CALL_BEFORE_SLEEP)) eventLoop-beforesleep(eventLoop); if (eventLoop-aftersleep ! NULL flags AE_CALL_AFTER_SLEEP) eventLoop-aftersleep(eventLoop);作用beforeSleep处理客户端写回、检查阻塞超时、计算下一次epoll_wait的超时时间等。

afterSleep清理或重置休眠期间的状态。

这些钩子避免了无限循环中 CPU 空转是 Redis 高效的核心之一。

睡眠钩子的实现beforeSleep钩子和afterSleep钩子的实现都在server.c中分别是void beforeSleep(struct aeEventLoop *eventLoop)和void afterSleep(struct aeEventLoop *eventLoop)。

实现上beforeSleep远比afterSleep复杂。

Epoll 实战键盘输入监听我们可以编写代码练习epoll的使用模拟 Redis 的事件监听机制。

#includestdio.h#includestdlib.h#includesys/epoll.h#includeunistd.h// 简单的错误处理宏#definepanic(fmt,...)\do{fprintf(stderr,FATAL ERROR: fmt (%s:%d)\n,##__VA_ARGS__,__FILE__,__LINE__);\exit(

;}while(

typedefstructepoll_eventEvent;intmain(void){intepfdepoll_create(

;if(epfd

{panic(epoll_create);return1;}// 设置监听标准输入键盘Event ev;ev.eventsEPOLLIN;ev.data.fdSTDIN_FILENO;if(epoll_ctl(epfd,EPOLL_CTL_ADD,STDIN_FILENO,ev)

{panic(epoll_ctl);return1;}Event events[10];charbuf[1024];// 事件循环for(;;){intnfdsepoll_wait(epfd,events,10,-

;if(nfds

{panic(epoll_wait);return1;}// 处理就绪事件for(inti0;infds;i){if(events[i].data.fdSTDIN_FILENO){intnreadread(STDIN_FILENO,buf,sizeof(buf));if(nread

{buf[nread]\0;printf(键盘输入: %s,buf);}}}}close(epfd);return0;}编译运行gcc epoll_test.c -o epoll_test ./epoll_test这个程序会在没有输入时“睡眠”输入内容按回车后被唤醒完美模拟了 Redis 的事件处理模型。

糖心VOLG-糖心应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123