5. 多线程程序如何让 IO 和“计算”相互重叠,降低 latency?

基本思路是,把 IO 操作(通常是写操作)通过 BlockingQueue 交给别的线程去做,自己不必等待。

例1: logging

在多线程服务器程序中,日志 (logging) 至关重要,本例仅考虑写 log file 的情况,不考虑 log server。

在一次请求响应中,可能要写多条日志消息,而如果用同步的方式写文件(fprintf 或 fwrite),多半会降低性能,因为:

  • 文件操作一般比较慢,服务线程会等在 IO 上,让 CPU 闲置,增加响应时间。
  • 就算有 buffer,还是不灵。多个线程一起写,为了不至于把 buffer 写错乱,往往要加锁。这会让服务线程互相等待,降低并发度。(同时用多个 log 文件不是办法,除非你有多个磁盘,且保证 log files 分散在不同的磁盘上,否则还是受到磁盘 IO 瓶颈制约。)

解决办法是单独用一个 logging 线程,负责写磁盘文件,通过一个或多个 BlockingQueue 对外提供接口。别的线程要写日志的时候,先把消息(字符串)准备好,然后往 queue 里一塞就行,基本不用等待。这样服务线程的计算就和 logging 线程的磁盘 IO 相互重叠,降低了服务线程的响应时间。

尽管 logging 很重要,但它不是程序的主要逻辑,因此对程序的结构影响越小越好,最好能简单到如同一条 printf 语句,且不用担心其他性能开销,而一个好的多线程异步 logging 库能帮我们做到这一点。(Apache 的 log4cxx 和 log4j 都支持 AsyncAppender 这种异步 logging 方式。)

例2: memcached 客户端

假设我们用 memcached 来保存用户最后发帖的时间,那么每次响应用户发帖的请求时,程序里要去设置一下 memcached 里的值。这一步如果用同步 IO,会增加延迟。

对于“设置一个值”这样的 write-only idempotent 操作,我们其实不用等 memcached 返回操作结果,这里也不用在乎 set 操作失败,那么可以借助多线程来降低响应延迟。比方说我们可以写一个多线程版的 memcached 的客户端,对于 set 操作,调用方只要把 key 和 value 准备好,调用一下 asyncSet() 函数,把数据往 BlockingQueue 上一放就能立即返回,延迟很小。剩下的时就留给 memcached 客户端的线程去操心,而服务线程不受阻碍。

其实所有的网络写操作都可以这么异步地做,不过这也有一个缺点,那就是每次 asyncWrite 都要在线程间传递数据,其实如果 TCP 缓冲区是空的,我们可以在本线程写完,不用劳烦专门的 IO 线程。Jboss 的 Netty 就使用了这个办法来进一步降低延迟。

以上都仅讨论了“打一枪就跑”的情况,如果是一问一答,比如从 memcached 取一个值,那么“重叠 IO”并不能降低响应时间,因为你无论如何要等 memcached 的回复。这时我们可以用别的方式来提高并发度,见问题8。(虽然不能降低响应时间,但也不要浪费线程在空等上,对吧)

另外以上的例子也说明,BlockingQueue 是构建多线程程序的利器。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tomcat web应用_具有可执行Tomcat的独立Web应用程序

tomcat web应用在部署应用程序时,简单性是最大的优势。 您将了解到,尤其是在项目发展且需要在环境中进行某些更改时。 将您的整个应用程序打包到一个独立且自足的JAR中似乎是个好主意,特别是与在目标环境中安装和升级Tomcat相比。 过去&#…

anaconda在ubuntu中添加环境变量

在ubuntu上安装好anaconda后,如果输入conda命令报错,很有可能需要以下修改注册表(相当于windows中将路径添加到系统环境变量) ~ /anaconda3/bin为.Sh所在home目录路径 在终端输入:sudo gedit ~/.bashrc 打开注册表后…

webpackjsonp 还原_具有催化CO2还原性能的非贵金属配合物的配体设计

Non-noble metal-based molecular complexes for CO2 reduction: From the ligand design perspectiveDong-Cheng Liu, Di-Chang Zhong, Tong-Bu LuEneryChem, 2, 100034 (2020).DOI: https://doi.org/10.1016/j.enchem.2020.100034全文链接https://www.sciencedirect.com/jour…

【数据库系统概论】第3章-关系数据库标准语言SQL(1)

文章目录 3.1 SQL概述3.2 学生-课程数据库3.3 数据定义3.3.1 数据库定义3.3.2 模式的定义3.3.3 基本表的定义3.3.4 索引的建立与删除3.3.5 数据字典 3.1 SQL概述 动词 分类 三级模式 3.2 学生-课程数据库 3.3 数据定义 3.3.1 数据库定义 创建数据库 tips:[ ]表…

适用于Java开发人员的Elasticsearch教程

课程大纲 Elasticsearch是基于Lucene的搜索引擎。 它提供了具有HTTP Web界面和无模式JSON文档的分布式多租户全文搜索引擎。 Elasticsearch是用Java开发的,并根据Apache许可的条款作为开源发布。 Elasticsearch是最受欢迎的企业搜索引擎,紧随其后的也是基…

shell实战之tomcat看门狗

1、脚本简介 tomcat看门狗,在tomcat进程异常退出时会自动拉起tomcat进程并记录tomcat运行的日志。 1 函数说明: 2 log_info:打印日志的函数,入参为需要在日志中打印的msg 3 start_tom:启动tomcat的函数…

tensorflow tf.train.batch()

tf.train.batch([example, label],batch_sizebatch_size, capacitycapacity) [example, label]表示样本和样本标签,这个可以是一个样本和一个样本标签,batch_size是返回的一个batch样本集的样本个数。capacity是队列中的容量。这主要是按顺序组合成一个b…

苹果6s上市时间_iPhone7的A10处理器还能战多长时间?2-3年不成问题!

iPhone 7采用A10 Fusion处理器,简称A10处理器,在2018年依然是处于高端处理器,再加上苹果自己的系统优化和资源调度,流畅度甚至超过其他安卓835机子。16年上市的iPhone7的A10还能再战多长时间?小编今天来分析一下。A10处…

tf.summary.FileWriter

ummary_waiter tf.summary.FileWriter("log",tf.get_default_graph()) log是事件文件所在的目录,这里是工程目录下的log目录。第二个参数是事件文件要记录的图,也就是tensorflow默认的图。

83998 连接服务器出错_服务端 TCP 连接的 TIME_WAIT 问题分析与解决

民工哥技术之路 写在开头,大概 4 年前,听到运维同学提到 TIME_WAIT 状态的 TCP 连接过多的问题,但是当时没有去细琢磨;最近又听人说起,是一个新手进行压测过程中,遇到的问题,因此,花…

SqlServer 时间格式化

select GETDATE() as 当前日期, DateName(year,GetDate()) as 年,DateName(month,GetDate()) as 月,DateName(day,GetDate()) as 日,DateName(dw,GetDate()) as 星期,DateName(week,GetDate()) as 周数,DateName(hour,GetDate()) as 时,DateName(minute,GetDate()) as 分,DateN…

[EBOOK]十大Java性能问题

有兴趣了解更多吗? 然后,您应该在此处下载相关的电子书。 Java中的大多数性能问题都可以归因于一些根本原因。 当然,偶尔会有一些奇怪的极端情况突然出现,并在应用程序中造成了严重破坏,但是在大多数情况下&#xff0…

请上传sku预览图后重新操作_拼多多商家版APP新增商品操作步骤

① 点击右下角“添加商品”按钮,进入创建商品页面;② 快速创建商品:目前手机版支持快速上传商品啦:仅通过上传商品标题、商品轮播图、商品分类、价格和库存,点击创建按钮,即可快速上传您的第一件店…

消息队列概述[幻灯片]

昨天我发表了一个演讲,涉及使用消息队列的所有方面。 我以前曾写过“您可能不需要消息队列” –现在的结论有些细微差别,但我仍然坚持简单性的观点。 演讲探讨了使用消息队列的各种好处和用例,并讨论了典型“消息队列代理”体系结构的替代方…

tf.reshape()

_image tf.reshape(x, [-1,28, 28, 1]) # -1表示任意数量的样本数,大小为28x28深度为一的张量 # 可以忽略(其实是用深度为28的,28x1的张量,来表示28x28深度为1的张量)

面向对象进阶-反射(二)重要知识点

# 面向对象的进阶# 其他常用模块# 作业 考试题# 网络编程 2天# ftp作业# class A:pass# class B(A):pass# a A()# print(isinstance(a,A))返回true,判断a是不是A的对象# print(issubclass(B,A))返回true,判断B是不是A的子类# print(issubclass(A,B))》…

异步过程的自动化测试

自从我开发了具有异步行为的服务器端应用程序以来已经有一段时间了,该行为还不是事件驱动的系统。 异步行为始终是设计和测试中一个有趣的挑战。 通常,异步行为不应该很难进行单元测试-毕竟,动作的行为不一定必须在时间上进行耦合&#xff08…

iphone以旧换新活动_iPhone第3轮降价背后:销售下滑库克甩锅给中国,国产手机崛起分食蛋糕...

排版 | 王科编辑 | 梁夜作者 | 吴晓宇来源 | 财经天下周刊(ID:cjtxzk)曾经吃掉手机行业9成利润的巨无霸公司苹果,不得不“自降身价”。3月5日之后,苏宁易购、京东、拼多多等多家电商平台纷纷宣布,再次对旗舰级iPhone XS系列产品降…

tf.placeholder()

# x 是手写图像的像素值,y是图像对应的标签 x tf.placeholder(tf.float32, [None,784])y tf.placeholder(tf.float32, [None,10])

Docker 搭建pxc集群 + haproxy + keepalived 高可用(二)

上一节我们有了两个分片的pxc集群,这一节我们接着安装haproxy和keepalived的实现集群的高可用 一、先下载haproxy的镜像 [rootlocalhost ~]# docker pull haproxy二、在host主机上写好配置文件,启动容器时候读取haproxy.cfg,vim /usr/local/d…