开发高性能ASP.NET应用

本文是“.NET Conf China 2022”上我的一个分享,这里更细化的分享出来。

分享分为四个部分:

  1. 制定指示

  2. 设计应用

  3. 正确测试

  4. 性能优化

高性能:不一定是架构出来的,但一定是优化出来的。

  • 制定指标-收集

    首先把项目中的热路径API和核心API找出来,然后分析每个API是CPU密集型的,还是内存密集型的,以供在后面测试参考或对API的判断。

  • 制定指标-制定

    TPS=并发线程*1000/ART,这是TPS和平均响应时间的公式。这里的表格相对完整,作为开发的性能测试,有时也可以只要求响应时间和TPS。或要求TPS和P95,P99。有时成功率很敏感,不管发性能怎么样,成功率必须100%,这是根据业务的类型要求的,特别是和钱有关的请求,要求都比较高。

    某API指标

    指标名称

    指标值

    业务指标

    TPS(2C2G)

    2000

    响应时间

    ART

    10

    P95

    12

    P99

    15

    成功率

    100%

    并发线程

    20

    稳定性指标

    压力持续时间

    >=8h

    压力阈值

    CPU <80%,TPS≈2000

    内存泄露

    TPS波动

    <5%

    应用资源(2C2G)

     MEM

    <2G

    CPU最大使用率

    <90%

    DB资源(8C8G)

     MEM

    <8G

    CPU最大使用率

    <90%

    缓存(1C1G)

    MEM

    <80%

    CPU最大使用率

    <90%

  • 设计应用-通用设计

    开发人员要了解通用状态下的设备情况,比如CPU的缓存,内存,硬盘之间的关系,比如速度是在依次减少,成本在降低。还要了解各种网络协速度,I/O的速度,以及使用各种数据库的速度通常的阈值是什么样的。

762e1f158e6b6697641758c0f5ac08e4.png

提升性能的两个法宝:用缓存和用Queue,缓存可以让使用数据速度更快,Queue可以分隔复杂业务,让吞吐量更高,合理有效的使用两种技术可以很大的提升性能。

  • 设计应用-.NET体系

  • 使用异步:Demo

//同步方法
app.MapGet("/sync", () =>
{using (var con = new MySqlConnection(connectionString)){var result = con.Query<int>("select sleep(6)");Console.WriteLine($"sync:{DateTime.Now}");return result;}
});
//异步方法,没有CancellationToken 
app.MapGet("/async", async () =>
{using (var con = new MySqlConnection(connectionString)){var result = await con.QueryAsync<int>("select sleep(6)");Console.WriteLine($"sync:{DateTime.Now}");return result;}
});
//异步,有CancellationToken 
app.MapGet("/asyncwithtoken", async (CancellationToken token) =>
{using (var con = new MySqlConnection(connectionString)){var result = await con.QueryAsync<int>(new CommandDefinition("select sleep(6)", cancellationToken: token));Console.WriteLine($"sync:{DateTime.Now}");return result;}
});

通过postman请求三个api,然后取消,会发现前两个api始终会执行完成,并输出时间;第三个会在取消后停止响应。

58fcce56ae5e58649eea1b97c6aec1e7.png

正确使用异步,可以有效地提升服务端的资源使用状况。

  • 谨防阻塞:

记一次性能故障排查

桂素伟,公众号:桂迹记一次性能故障排查

  • 大集合化整为零:用最正确的集合来处理数据,不要在集中存放大量数据,这样不管对内存或之后的运算,造成负担。同时要从业务层次评估计集合的最大上限。 

  • 避免在Host生成文件

再记一次Memory Leak分析

桂素伟,公众号:桂迹再记一次Memory Leak分析

  • 复杂方法要比对:

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using PerformanceDemo;
using System.Collections.Generic;
using System.Xml.Linq;var summary = BenchmarkRunner.Run(typeof(CustomTypeTest));public class CustomTypeTest
{ [Benchmark][Arguments(2000)]public Dictionary<string, SBook> GetBook1(int count){var sbookDic = new Dictionary<string, SBook>();for (var i = 0; i <= count; i++){sbookDic.Add($"张{i}丰", new SBook(){Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return sbookDic;}[Benchmark][Arguments(2000)]public Dictionary<string, Book> GetBook2(int count){var bookDic = new Dictionary<string, Book>();for (var i = 0; i <= count; i++){bookDic.Add($"张{i}丰", new Book(){Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return bookDic;}[Benchmark][Arguments(2000)]public List<Book> GetBook3(int count){var bookList = new List<Book>();for (var i = 0; i <= count; i++){bookList.Add(new Book{Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return bookList;}[Benchmark][Arguments(2000)]public List<SBook> GetBook4(int count){var sbookList = new List<SBook>();for (var i = 0; i <= count; i++){sbookList.Add(new SBook{Id = i,Name = "C#从入门到精通",Author = $"张{i}丰",Title = "C#1.0",Description = "这是一本书"});}return sbookList;}
}
public class Book
{public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }public string Title { get; set; }public string Author { get; set; }
}
public struct SBook
{public int Id { get; set; }public string Name { get; set; }public string Description { get; set; }public string Title { get; set; }public string Author { get; set; }
}

下面是比较结果:

28ec49fdbbb03dab584922b701c4a249.png

  • 让每个API轻巧快速

  • 有一颗追求性能的心——关注.NET版本

    关于在开发层次的性能注意事项有很多,这是根据不同的项目,使用不同的类库决定的,上面只是我性能化化中的几个代表性场景。

  • 设计应用-发布

配置:GC方式 工作站方式,服务器方式:CPU使用率比内存更重要,服务器GC性能更好;内存利用率较高而 CPU 使用率相对较低,工作站 GC 性能更高。

发布方式:默认和R2R首次请求时间和体积不同


普通模式

R2R模式

AOT模式

大小

29.8 MB

62.2 MB

19.5M

首次请求用时

360ms

90ms

20ms

  • 正确测试

  • 测性能的正确姿势

尽量与生产环境一致

要有监控,通过监控数据对比发现问题

不要打满资源:CPU<90%,内存少于最大值

让子弹多飞会儿,观察内存是有什么不一样

  • 遇到问题借助工具

dotnet-dump

dotnet-counters

  • 前人经验也很宝贵

https://learn.microsoft.com/zh-cn/dotnet/core/diagnostics/

  • 性能优化

  • 减少响应时间:

优化&简化流程

优化调用链路上的函数

把关系数据库操作转成缓存操作

用BenchmarkDotNet

  • 提升TPS:

优先降低性能测中的较高资源

让应用性能是线性的,可以轻松地通过扩容来提升TPS

经过上面的分享,可以得出:

高性能:一定是架构出来的,但一定是优化出来的。

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

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

相关文章

Ethereum-EIPs

What is an EIP? Ethereum Improvement Proposal 以太坊改进建议的文档 这个文档向Ethereum社区提供信息&#xff0c;为Ethereum、Ethereum的进程、环境描述一个新特征&#xff0c;该EIP应当为该特征提供一个基本的技术描述和原理原理。该EIP作者有责任在社区和不同意见的文档…

Django08-1:模型层(ORM)--聚合查询/分组查询/F与Q查询/开启事务/常用字段及参数/自定义字段/数据库查询优化

聚合查询 单独使用时&#xff0c;用aggregate 1.只要是跟数据库相关的模块 基本都在django.db.models里面 如果没有应该在django.db里面 2. 聚合查询通常配合分组使用 from django.db.models import Avg, Sum, Max, Min, Count# 1.所有书的平均价格 resmodels.Book.objects.…

记事本状态栏不会自动_如何在记事本中同时启用状态栏和自动换行

记事本状态栏不会自动The status bar in Windows’ Notepad displays the current line number and column number of the cursor location. However, if you find that the Status Bar option on the View menu is grayed out, it may be because you have Word Wrap enabled…

洛谷P2587 [ZJOI2008] 泡泡堂

题目传送门 分析&#xff1a;一道策略游戏题&#xff0c;要求最大期望得分和最小期望得分。首先分析最大&#xff0c;很显然是可以用一种类似于田忌赛马的思维来做&#xff0c;将两队的实力按照从大到小&#xff08;其实从小到大也可以&#xff09;排序&#xff0c;然后就按照顺…

极端高温导致澳大利亚断网

&#xfeff;西澳大利亚首府珀斯因恶劣天气出现了网络连接问题&#xff0c; 网络故障不是由于暴风雨或闪电引起的&#xff0c;而是极端高温。本周一是珀斯有记录以来第六热的天&#xff0c;当天最高温度达到了44.4℃。因为创纪录的高温&#xff0c;澳大利亚宽带 服务商iiNet在当…

推荐一款采用 .NET 编写的 反编译到源码工具 Reko

今天给大家介绍的是一款名叫Reko的开源反编译工具&#xff0c;该工具采用C#开发&#xff0c;广大研究人员可利用Reko来对机器码进行反编译处理。我们知道.NET 7 有了NativeAOT 的支持&#xff0c;采用NativeAOT 编译的.NET程序 无法通过ILSpy 之类的传统工具得到源码&#xff0…

并行传输数据和串行传输数据_为什么串行数据传输比并行数据传输快?

并行传输数据和串行传输数据SATA hard drive connections are faster than older PATA hard drive connections and the same can be said for external cabling standards, but this is counter-intuitive: why wouldn’t the parallel transmission be faster? SATA硬盘驱动…

得到某月的天数

Calendar timeCalendar.getInstance(); time.clear(); time.set(Calendar.YEAR,2018);//year年 time.set(Calendar.MONTH,1);//Calendar对象默认一月为0,month月 int daytime.getActualMaximum(Calendar.DAY_OF_MONTH);//本月份的天数 System.out.pri…

Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式

图书管理系统笔记 redirect括号内可以直接写url 也可以直接写别名 但如果别名需要参数&#xff0c;必须使用reverse解析。 choices用法 使用场景&#xff1a;能列举完全的数据 #使用方法&#xff1a;xxx_choice #1. get.xxx_display #2. 如果超出范围&#xff0c;则显示原…

业务处理速度变慢?且看IT如何成为救世主

在日常生活的方方面面&#xff0c;我们似乎都在期待着一种即时的便利。比如&#xff0c;用手机购物、订餐、缴费、预约挂号等等。而在企业中&#xff0c;时间与效率可不是一种休闲福利&#xff0c;而是一项重要的商业功能。我们有理由期待&#xff0c;当今史无前例的数字革命正…

微软让卡塔尔世界杯踏入元宇宙

遵守前一篇公众号文章里的承诺&#xff0c;昨天盆盆在视频号里录制了一段5分钟左右的短视频&#xff0c;讲了江森自控和微软Azure&#xff0c;如何帮助卡塔尔世界杯打造基于元宇宙的数字体育馆。Part.1欢迎扫码关注我的视频号(每天更新元宇宙、云计算和数字化的短视频)。Part.2…

洛谷——P1305 新二叉树(新建二叉树以及遍历)

题目描述输入一串二叉树&#xff0c;用遍历前序打出。 输入输出格式输入格式&#xff1a; 第一行为二叉树的节点数n。(n \leq 26n≤26) 后面n行&#xff0c;每一个字母为节点&#xff0c;后两个字母分别为其左右儿子。 空节点用*表示 输出格式&#xff1a; 前序排列的二叉树 输…

插槽1单通道插槽2双通道_相机双存储卡插槽有什么大不了的?

插槽1单通道插槽2双通道If you paid any attention to the launch of Canon and Nikon’s first full frame mirrorless cameras—the EOS R, Z6, and Z7— you’d have noticed that some people were pretty unhappy that they only came with a single card slot—an SD slo…

python 垃圾回收详解

原文&#xff1a;https://zhuanlan.zhihu.com/p/31150408 总纲策略和垃圾回收系统工作内容引用计数详解标记-清除分代收集循环引用编程应用-常见方法ex 过程详解使用建议触发机制参考文献Python垃圾回收机制--完美讲解&#xff08;Python vs Ruby&#xff09;Python垃圾回收机制…

Django10:Ajax介绍/发送数据/SweetAlert

Ajax 异步提交 局部刷新 发送方式 1. 浏览器输入url&#xff0c;按enter get 2.a标签href属性 get 3.form表单 get/post 4. ajax get/post ajax 不是编程语言&#xf…

物联网数据终端演进之道

智能手机的普及在最近几年掀起了一股取代企业数据终端的风潮&#xff0c;但正如笔者在一年前便提到过 的&#xff0c;“智能手机难以在企业级应用中得以普及”&#xff0c;这种观点最好的佐证便是时至今日&#xff0c;由于安全性与管理合规的需要&#xff0c;个人计算机用于企业…

mac 不能连接wi-fi_如何阻止Mac自动连接到Wi-Fi网络

mac 不能连接wi-fiYour Mac automatically reconnects to Wi-Fi networks you’ve previously connected to. Starting with macOS High Sierra, you can now tell your Mac not to automatically connect to certain Wi-FI networks. Your Mac will remember the Wi-Fi networ…

“玩转课堂”基本构想

1、项目背景随着互联网科技的高速发展&#xff0c;人们的生活、学习和工作中的许多事情都可以借助互联网来完成&#xff0c;并且反响良好。作为学生&#xff0c;我们切身体会到&#xff0c;能够使用网络平台来进行学习可以节约时间、并且十分方便&#xff1b;而在老师的角度&am…

SQLServer之分离数据库

分离数据库注意事项 要求具有 db_owner 固定数据库角色中的成员资格。 可以分离数据库的数据和事务日志文件&#xff0c;然后将它们重新附加到同一或其他 SQL Server实例。 如果要将数据库更改到同一计算机的不同 SQL Server 实例或要移动数据库&#xff0c;分离和附加数据库会…

django11:自动序列化/批量插入数据/分页器

自动序列化 借助serializers帮你自动完成序列化 from app01 import models from django.core import serializers def ab_se(request):user_queryset models.Userinfo.objects.all()#原始方法user_list []for user_obj in user_queryset:user_list.append({username:user_o…