设计极其糟糕的select函数

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情
设计极其糟糕的select函数
相较Windows而言,大部分UNIX API函数设计都比较考究,但也有少数简直就是奇葩,select函数正是这些奇葩中非常灿烂的一朵。我原来一致钟情于ACE,接触的只是reactor,最近由于开始自己设计网络层的类库,被迫和select打了一些交道,被迫和这个函数打了一些交道,结果只能是看着就吐了,吐着吐着就习惯了。
UNIX下select这个API由主函数select和几个fd_set辅助函数构成。如下:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);

void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);

//fd_set的实际结构是__kernel_fd_set
typedef struct {
unsigned long fds_bits [__FDSET_LONGS];
} __kernel_fd_set;
select主函数的第一个参数nfds的描述是 nfds is the highest-numbered file descriptor in any of the three sets, plus 1.也就是最大的文件句柄数值+1,这个参数的本质意图应该是加快内部处理的,避免内部处理几个fd_set的时候都不用处理次数,从而降低系统的计算销毁,但是select本来就是要处理3个fd_set,这个nfds就只能是这3个fd_set中间的最大值,而且考虑到nfds不可能一直增加,而不减少,在FD_CLR清理掉某个句柄后,找一个新的最大值,必须和3个fd_set打交道。简直是……,很多人,很多库的处理FD_CLR后,其实会偷懒不减少nfds。这个其实不是大家的错,而是select设计者的原罪。(当然你也可以像ACE那样包装一层加快实现)
改良的方案很简单,考虑到fd_set本来就只是内部的一个结构,每个结构拥有自己的最大值,是一件非常easy的事情。这样就可以取消那个讨厌的nfds参数。我们后面看Windows下的select设计时会继续讨论这个问题。
由于3个fd_set参数都是传入传出参数,所以如果是服务器程序,你老只好在每次调用select前保留一次这些句柄。
再来看看这个UNIX大部分设计中fd_set的实现,他就是一个用bit位标识文件句柄的long数组。所以他只能处理文件句柄数值小于1024的文件句柄,由于还有其他地方会占用前面的文件句柄ID,所以其实UNIX的select根本无法处理FD_SETSIZE个网络请求。甚至极端情况下你的程序一开始就打开了1024个文件,你就别想使用这个可爱的函数,他就没有这个处理能力……
Windows下的select函数基本向UNIX平台靠齐,但是由于Windows下HANDLE(SOCKET)完全不是整数(而是一个指针),Windows的select,可以实际处理FD_SETSIZE个文件句柄(Windows下这个参数默认64,可以在保护winsock2.h前面重新定义这个宏调整)。Windows下的select函数就没有使用第一个参数,其通过设计fd_set达到了同样加速的目的。
//Windows下的fd_set的定义
typedef struct fd_set {
//如果UNIX的fd_set也有这个参数,那么UNIXselect函数的处理也简单了
u_int fd_count; /* how many are SET? */
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} fd_set;
最后我们看看FD_ISSET的设计,大部分select的例子都是使用FD_ISSET判断某个句柄是否被触发的,但是真正我们写服务器时,如果要老老实实使用FD_ISSET,方法就只能是自己先保存一组放入select的句柄参数。然后将这些句柄取出一个个和返回的fd_set用FD_ISSET进行判断,所以这个成本至少是一个O(nfds),而在Windows下,由于句柄ID不可能直接映射查找。查询效率应该是O(输入参数fd_set的数量*触发返回的fd_set的数量)。Windows下有没有快一点的法子呢,有,就是不用FD_ISSET,直接利用fd_set的结构。处理效率就只需要O(触发返回的fd_set的数量),当然这又违背了select函数FD_ISEET这类函数(宏)的设计初衷,不希望你了解fd_set的内部结构。
整体说来,UNIX下的select函数的设计是完全是结合UNIX文件句柄的设计进行的,同时考虑了部分加快速度部分的处理,虽然在那个年代,也许有他的苦衷。但无需遮掩,其整体设计是比较失败的,既没有效率,也没有考虑扩展性,而Windows下select的设计比UNIX版本高出一节。而如果把epoll的API拿出来比一下,高下立分。

SAP ABAP SELECT语法深度解析:从基础到HANA性能优化实战 在数据库编程中,SQL查询是数据操作的核心,其性能直接影响系统响应与资源消耗。ABAP Open SQL作为SAP系统的标准查询语言,通过声明式语法将开发者意图转换为底层数据库指令,其设计哲学强调可移植性与优化器协同。理解SELECT语句的执行流——从FROM/WHERE的数据定位,到GROUP BY/HAVING的聚合筛选,再到ORDER BY的排序——是编写高效查询的基础。在SAP S/4HANA架构下,结合列式存储特性,合理利用索引、避免全表扫描成为关键性能实践。针对常见场景如多条件筛选与分页查询,需 阅读详情

相关推荐

告别手动输入!用POPUP_TO_SELECT_MONTH函数为ABAP选择屏幕添加优雅的年月选择器

本文详细介绍了如何使用SAP ABAP中的POPUP_TO_SELECT_MONTH函数为选择屏幕添加图形化年月选择器,取代易错的手动输入。通过基础集成、高级应用和用户体验优化技巧,帮助开发者提升报表的交互效率和用户友好度,特别适合财务、供应链等需要频繁选择日期范围的业务场景。

weixin_30394981的博客 243

[转载]Windows网络编程系列教程之四:Select模型

原文: http://www.51see.com/asp/bbs/public/bp_show.asp?t_id=200308131152297103 讲一下套接字模式和套接字I/O模型的区别。先说明一下,只针对Winsock,如果你要骨头里挑鸡蛋把UNIX下的套接字概念来往这里套,那就不关我的事。 套接字模式:阻塞套接字和非阻塞套接字。或者叫同步套接字和异步套接字。 套接字模型:描述...

weixin_30819085的博客 366

糟糕的用户体验设计:威胁数据安全的隐患!

本文讨论了糟糕的UX设计可能引发的信息泄露与隐私问题、恶意注入攻击和社会工程攻击,并提供了相应的源代码示例来阐述防范措施。然而,糟糕的用户体验设计不仅会影响用户的体验和满意度,还可能引发潜在的数据安全威胁。本文将探讨糟糕的UX设计如何成为数据安全的威胁,并提供相应的源代码示例。糟糕的UX设计可能会使用户更容易受到社会工程攻击的影响,例如通过误导性的界面设计、虚假的提示信息或伪装成合法来源的链接等手段。安全的存储方式:确保用户数据存储在安全的数据库中,采取必要的防护措施,如访问控制、备份和监控。

QoTypescript的博客 242

select引起的服务端程序崩溃问题

现象: 某个线上的服务最近频繁崩溃。该服务使用C++编写,是个网络服务端程序。作为TCP服务端,接收和转发客户端发来的消息,并给客户端发送消息。该服务跑在CentOS上,8G内存。线上环境中,与客户端建立的TCP连接大约在3~4万左右。 使用GDB查看每次崩溃产生的core文件,发现崩溃时的函数调用栈每次都各不相同,而且有时会发生在比较奇怪的地方,比如标准库std::stri...

weixin_30814329的博客 1413

细谈select函数(C语言)

      Select在Socket编程中还是比较重要的,可是对于初学Socket的人来说都不爱用Select写程序,他们只是习惯写诸如connect、accept、recv或recvfrom这样的阻塞程序(所谓阻塞方式block,顾名思义,就是进程或是线程执行到这些函数时必须等待某个事件的发生,如果事件没有发生,进程或线程就被阻塞,函数不能立即返回)。可是使用Select就可以完成非阻塞(所谓非阻塞方式non-block,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不

piaojun_pj的专栏 15万+

WindowsLinuxselect函数功能差异

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33910460的博客 242

SQL语句详解:SELECT查询的艺术

子句主要作用最佳使用场景WHERE在数据源级别过滤行需要减少参与计算的数据量时GROUP BY按指定列对结果分组需要汇总统计数据时HAVING过滤分组后的结果需要基于聚合结果筛选时ORDER BY对结果集排序需要按特定顺序展示数据时LIMIT限制返回的行数分页或只需要部分结果时窗口函数(又称分析函数)是SQL中的高级特性,允许我们在不改变结果集行数的情况下进行计算,这就像是给每行数据增加了"上下文感知"能力。-- 窗口函数基本语法SELECT窗口函数的核心组成部分。

sinat_27016095的博客 1684

【网络】高级IO——select版本TCP服务器

我们今天要讲的selectselect的原理就像下面的赵六一样。赵六去钓鱼,他是个小土豪,赵六手里拿了一堆鱼竿,目测有几百根鱼竿,赵六到达河边,首先就把几百根鱼竿每隔几米插上去,总共插了好几百米的鱼竿,然后赵六就依次遍历这些鱼竿,哪个鱼竿上的鱼漂动了,赵六就把这根鱼竿上的鱼钓上来,然后接下来赵六就又继续重复之前遍历鱼竿的动作进行钓鱼了。

2301_80224556的博客 1646

SELECT * 真相

转自 http://www.cnblogs.com/goodspeed/archive/2007/07/20/index_coverage.html SELECT *的效率很糟糕吗?当然,所有人都知道这一点,但是为什么呢?是因为返回了多的数据?这是一个普遍的回答,但我不这样认为。如果你的数据库设计规范合理,那么带宽占用实际上非常的小。让我们看看下面的例子。下面的查询将会从

oicqhf的专栏 1412

这数据库的结构设计,还能再糟糕一点吗?

数据库设计

m0_38048955的博客 430

记一次糟糕的 MyBatis-Plus 查询设计:那个“非得查 COUNT”的分页坑

《MyBatis-Plus分页设计的性能陷阱与优化实践》摘要: 文章揭示了MyBatis-Plus分页查询的两大痛点:1)默认强制COUNT查询导致性能浪费;2)参数Map设计造成前后端协作困难。作者通过实践提出优化方案:采用类型安全的Query对象替代Map参数提升可维护性,并通过PageResult封装实现逻辑隔离。尽管受限于框架无法完全避免COUNT查询,但建议通过职责分离(独立list/count方法)和减少分页插件使用来优化性能。核心观点指出:框架的便利性可能违背设计原则(如迪米特法则),高并发场

lfeishumomol的博客 1019

数据库设计中的9大常见错误

作为数据库设计人员,当我们负责数据库项目时,在数据库设计以及把数据库部署到生产环境的过程中可能会遇到一些挑战。其中一些问题不可避免,也无法控制。但是,其中相当一部分可以追溯到数据库设计本身的质量。我们在初步阶段所做的决定会对数据库最终的工作情况有深远的影响。糟糕的预规划如果我们要建一所房子,我们不会聘请一位工程承包商,然后马上就要求他们开始打地基。这会导致灾难发生。至少,我们需要就建房计划和蓝图达...

测试 2394

WPF/Silverlight的数据绑定设计的真糟糕

最近为了帮助大家找工作,专门建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。AND dimensions @> '{"category": "electronics"}'-- JSON包含查询。MySQL采用"一个连接一个线程"的模型,这种设计在连接数较多时会导致严重的性能问题。经过以上的分析,在高并能的场景中,我更推荐使用PostgreSQL,而非MySQL。-- PostgreSQL中,复杂的JSON查询也能高效执行。

csagafaw的博客 676
上一篇: CSDN 的blog改版后更加难用了。。。。。。
下一篇: 一线咨询师的絮絮叨叨
fullsail
博客等级 码龄25年 533粉丝 79原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值