当前位置: 首页 > news >正文

企业网站制作运营/整合营销传播

企业网站制作运营,整合营销传播,python数据分析做网站,b2c网站资讯使用.NET简单实现一个Redis的高性能克隆版(二)[1]译者注该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单、高性能兼容Redis协议的数据库的经历。首先这个"Redis"是非常简单的实现,但是他在优化这个简单"Redis…

使用.NET简单实现一个Redis的高性能克隆版(二)[1]

译者注

该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单、高性能兼容Redis协议的数据库的经历。首先这个"Redis"是非常简单的实现,但是他在优化这个简单"Redis"路程很有趣,也能给我们在从事性能优化工作时带来一些启示。原作者:Ayende Rahien 原链接:https://ayende.com/blog/197441-A/high-performance-net-building-a-redis-clone-analysis 另外Ayende大佬是.NET开源的高性能多范式数据库RavenDB所在公司的CTO,不排除这些文章是为了以后会在RavenDB上兼容Redis协议做的尝试。大家也可以多多支持,下方给出了链接 RavenDB地址:https://github.com/ravendb/ravendb

正文

在上一篇文章中[2],我用最简单的方式写了一个Redis克隆版本。它能够在我们的测试实例上每秒命中近100万个查询(c6g.4xlarge,使用16个内核和64 GB内存)。在我们更深入地进行优化之前,值得了解CPU时间实际花费在哪里。我在探查器下运行服务器,以查看各种代码所耗费的成本。我喜欢使用dotTrace作为探查器,同时使用它的跟踪模式,因为它返回的数据中给了我各个模块、类和代码的执行时间以及调用次数。通常,我可以仅从这些细节中推断出很多关于系统性能的原因。看看下面的统计数据,这是连接实际处理过程中的成本细分:

692bcc86d4fb69cb0de22cbc869c9962.png
img

[3] 展开耗费CPU最多的System code,如下所示:

f65779e5f4ac675fada0653d62faaf77.png
img
[4]您可以看到FlushAsync()方法耗费的CPU做多。我们在这里做一个假设,当我们调用StreamWriterFlushAsync()方法时,同样会刷新底层的流。深入研究下调用栈,似乎我们在TCP层面为每个命令都都进行了分包,这样效率是很低的。如果我们将StreamWriterAutoFlush属性改为true,这将导致它立即向网络流中写入数据,但不会在TCP流上调用flush,这会让TCP流更有效的利用缓冲空间。涉及的代码更改是删除FlushAsync()调用并初始化StreamWiter,如下所示:
using var writer = new StreamWriter(stream)
{NewLine = "\r\n",AutoFlush = true,
};

让我们再次运行基准测试,这将给我们(在我的开发机器上):

•138,979.57 QPS [13.8w/s]– 使用 AutoFlush = true•139,653.98 QPS [13.9w/s]– 使用 FlushAsync 基本上,这两种选择都不怎么样。原因如下所示:设置为True的AutoFlush不仅会刷新当前流,还会刷新基础流,从而使Stream他们处于相同的Position。问题是我们需要刷新流,否则我们在内存中缓冲的结果数据不会发送给客户端。Redis基准测试在很大成都依赖管道(一次性发送多个命令),但是在实际过程中可能会收到一堆来自客户端的命令,这堆命令会写入(到输入缓冲区),然后不向客户端发送任何内容,因为输出的缓冲区并没有满。我们可以使用以下代码更改轻松地优化它:

var line = await reader.ReadLineAsync();
await writer.FlushAsync();
// 修改为以下代码
var lineTask = reader.ReadLineAsync();
if(lineTask.IsCompleted == false)
{await writer.FlushAsync();
}
var line = await lineTask

我在这里所做的是直接写入StreamWriter,并且只有在没有更多的输入时才刷新缓冲区。这应该会大大减少包的发送次数,而且它确实做到了。再次运行基准测试可以得出以下结论:

•229,783.30 QPS [22.9w/s] – 使用延时刷新 我们只修改几行代码,却得到了几乎两倍的性能提升,这是令人影响深刻的。我们的想法是,缓冲更多的写入,并且不让它延时太久。如果写入足够的数据到StreamWriter缓冲区,它自己会自动的刷新。我们只会在没有其它需要读取的数据时手动刷新StreamWriter,这个操作是和读取并行进行的。下图是新的耗时统计:

ab5674fd494f15ea4c44c903fb98a808.png
img

[5] 实际方法调用如下:

8ddd9fad9c8446cfb4641117ec2371f5.png
img
[6]如果我们将其与第一次分析结果进行比较,我们可以发现一些非常有趣的数字。以前,我们为每个命令调用FlushAsync(请参阅ExecuteCommand&FlushAsync),现在我们更少调用它了。您可以看到,现在大部分时间花费都在这个系统的“业务逻辑代码”中,从子系统的细分来看,现在很多时间都花费在处理集合中。这里的GC花费也大幅下降(~5%)。我相当确定这是因为我们使用了新的方式刷新TCP流,但我没有仔细的去检查它。请注意,虽然字符串处理和GC需要花费大量时间,但是集合/ExecuteCommand还是占用了更多的时间。如果我们调查一下,我们会发现:9d3a65b8baa29e426a4ac0ce6366ee7d.png
img
[7]而且这非常有趣。主要是因为主要成本在TryAddInternal中。我们知道在这种情况下存在很高的争用,但92%的时间直接花在了这个方法上吗?让我们看一下代码,它在做什么就会很明显:6ca7c76df0de96cbd6c92fc8fc6654ed.png
img
[8]

ConcurrentDictionary对锁之间的调用进行分片。锁的数量由我们默认拥有的CPU内核数量定义。我们的的并发越多,我们就越能从增加分片数量中获益。我尝试将其设置为1024,并在分析器下运行它,这给我带来了几个百分点的改进,但并不是很多。很有价值,但不是我期望的水平。

88162b09e99418ced4a525a83d392199.png
img

[9] 现在,我们需要找出如何在让集合操作变得更快,但我们还必须考虑总体GC成本以及字符串处理细节。在下一篇文章中会有更多关于这一点的信息。

系列链接

使用.NET简单实现一个Redis的高性能克隆版(一)[10]

作者:InCerry

作者Github:https://github.com/incerrygit

出处:https://www.cnblogs.com/InCerry/p/Use-Dotnet-Make-A-Simple-High-Performance-Redis-2.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际[11]」许可协议进行许可。

声明:本博客版权归「InCerry[12]」所有。

欢迎大家关注我的微信公众号,新文章会优先发到公众号!

6239842e588e3c10f5acaf7605784f61.png
img

References

[1] 使用.NET简单实现一个Redis的高性能克隆版(二): https://www.cnblogs.com/InCerry/p/Use-Dotnet-Make-A-Simple-High-Performance-Redis-2.html
[2] 上一篇文章中: https://www.cnblogs.com/InCerry/p/Use-Dotnet-Make-A-Simple-High-Performance-Redis.html
[3]

4baa776cac0713d9ea1e4c84b65de3f2.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093927811-287918144.png
[4]

30a63a16bb2c5d5893cbe96bcac7e6a6.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093927446-1067937611.png
[5]

d161a1b42aaff15a784ed91b156c9dde.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093927095-661976682.png
[6]

2493669888419d001f7f7caaa43238ab.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093926753-688046364.png
[7]

3a28b7c1f7bf72b87eeaaf40dd4db435.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093926367-217820360.png
[8]

722432d61ff3389030a5fea4f3d1df20.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093925876-270175850.png
[9]

f482ddfa0da1489fa4a8939714d0bc6d.png
img

https://img2022.cnblogs.com/blog/997046/202208/997046-20220804093925103-334453984.png
[10] 使用.NET简单实现一个Redis的高性能克隆版(一): https://www.cnblogs.com/InCerry/p/Use-Dotnet-Make-A-Simple-High-Performance-Redis.html
[11] 署名-非商业性使用-相同方式共享 4.0 国际: https://creativecommons.org/licenses/by-nc-sa/4.0/
[12] InCerry: https://incerry.cnblogs.com/

http://www.lbrq.cn/news/816139.html

相关文章:

  • 禅城网站制作/软文写作的十大技巧
  • 网站别人做的收到方正侵权/钟南山今天感染新冠了
  • 加强主流网站集群传播能力建设/win10优化工具
  • 网站数据库密码修改了要怎么做/外链免费发布平台
  • 网站 工信部备案 收回/广州seo和网络推广
  • 网站建设胶州家园/济南网络推广网络营销
  • 海南省住房公积金管理局app/seo是哪个英文的缩写
  • 百货店怎么做网站送货/百度app在哪里找
  • 网站的分页效果怎么做/seo关键词平台
  • 网站内外链怎么做/品牌宣传文案范文
  • 网站建设交互效果/it培训机构推荐
  • 如何做网站接口/酒吧营销用什么软件找客源
  • 网站运营方案案例/短视频推广策略
  • 东莞网站平面设计/百度推广点击软件
  • 用web做的网站吗/常州网站建设书生商友
  • 校园网站建设的意义/搜索引擎优化的含义
  • 怎么做游戏测评视频网站/火狐搜索引擎
  • 学校资源网站建设方案/除了91还有什么关键词
  • 光电网站设计/深圳哪里有网络推广渠避
  • ecshop做企业网站/广告推广怎么做最有效
  • 特色食品网站建设策划书/海外营销方案
  • 如何做网站结构分析/草莓永久地域网名入2022
  • 卡密商城平台/seo宣传网站
  • 公司网站开发模板/属于网络营销的特点是
  • 银川制作网站/自己怎么优化网站排名
  • wap手机建站平台/体验式营销经典案例
  • 招商网站大全/网站如何做优化推广
  • 做新闻的网站怎样赚钱/湖南企业seo优化
  • 吉林建设监理协会网站/网络宣传的方法有哪些
  • 毕业设计做视频网站设计/视频专用客户端app
  • 从零开始的云计算生活——第三十六天,山雨欲来,Ansible入门
  • Rust嵌入式开发实战
  • Android Studio 提示信息 ‘equals(““)‘ can be replaced with ‘isEmpty()‘
  • VTK交互——Callback
  • 二叉搜索树(Binary Search Tree)详解与java实现
  • NodeJS搭建SSE接口服务