網站首頁 編程語言 正文
異常和正常代碼性能旗鼓相當,但是全局過濾器對性能影響比較大,大概降低了60%左右,全局過濾器走了管道,但是這跟微軟官方的性能優化又有沖突,想必微軟官方也是出于對全局過濾器異常處理的考慮吧。同時對于添加了業務的情況下,這個降低會被稀釋,沒去做壓測對比哈,正常用戶體量還不至于被這個給影響到穩定性。所以怎么取舍看自己
一、前言
在.net 相關技術群、網絡上及身邊技術討論中看到過關于大量拋異常會影響性能這樣的結論,心中一直就存在各種疑問。項目中使用自定義異常來處理業務很爽,但是又擔心大量拋業務異常存在性能問題。
查閱了各種文檔,微軟官方對性能優化這一塊也不建議使用過多的異常,故我心中冒出疑問。
- 疑問一:項目中大量拋出業務異常對性能是否會受到影響?
二、求證
2.1 使用.net 6 建立了一個簡單的web api 項目 新增兩個壓測接口api接口代碼如下
/// <summary>
/// 正常返回數據接口1
/// </summary>
/// <returns></returns
[HttpGet("Test1")]
public async Task<IActionResult> Test()
{
return Content("1");
}
/// <summary>
/// 拋異常返回接口2 ,同時存在全局過濾器
/// </summary>
/// <returns></returns
[HttpGet("Test2")]
public async Task<IActionResult> Test2(string open)
{
throw new BusinessException(Model.EnumApiCode.SignWrong);
}
全局過濾器代碼如下
/// <summary>
/// 全局異常日志
/// </summary>
public class ExceptionFilter : IExceptionFilter
{
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public void OnException(ExceptionContext context)
{
//不做任何處理,直接返回1
context.Result = new JsonResult("1");
}
}
//全局過濾器注入
services.AddControllers()
.AddMvcOptions(option =>
{
option.Filters.Add<ExceptionFilter>();
});
現在對test1 接口并發200的情況下進行壓測,持續15分鐘的壓測結果如下:
對通過全局過濾器捕獲異常并大量拋出異常 在相同壓測條件情況下的壓測結果如下:
對test1 和test2 同等條件下壓測結果對比
接口 | tps | cpu | 壓測條件 |
---|---|---|---|
test1 | 10300左右 | cpu消耗90%左右 | 并發200,持續壓測 |
test2 | 4300左右 | cpu消耗100%左右 | 并發200,持續壓測 |
目前得到的結論是拋異常確實影響性能,并且對性能下降了60% 左右,上面主要是異常流程走了全局過濾器方式,故參考意義不大,下面再進一步修改代碼進行壓測
對test2 代碼進行修改如下
/// <summary>
/// 拋異常返回接口2 ,直接try catch 不走全局過濾器
/// </summary>
/// <returns></returns
[HttpGet("Test2")]
public async Task<IActionResult> Test2()
{
try
{
throw new BusinessException(Model.EnumApiCode.SignWrong);
}
catch (Exception ex)
{
return Content("1");
}
}
再對修改后的test2 接口進行壓測,壓測結果如下:
接口 | tps | cpu占用 | 壓測條件 |
---|---|---|---|
test1 | 10300左右 | 90% 左右 | 并發200,持續壓測 |
test2 | 9200左右 | 91% 左右 | 并發200,持續壓測 |
進一步得到的結論是try catch 后性能有所提高,跟正常相比還有點點差距,全局過濾器對性能影響比較大,相當于走了管道,但是觀察代碼test1 和test2代碼還存在差距,懷疑test2 代碼中new 了新異常導致性能差異,故再進一步進行代碼修改求證
對test1 代碼進行修改,修改后的代碼如下:
/// <summary>
/// 正常返回數據接口1,但是先new 異常出來,保持跟上面test2 代碼一致
/// </summary>
/// <returns></returns
[HttpGet("Test2")]
public async Task<IActionResult> Test2(string open)
{
var ex= new BusinessException(Model.EnumApiCode.SignWrong);
return Content("1");
}
對修改后的test1 代碼進行壓測結果如下:
忘記截圖,大概和修改后的test2 代碼壓測結果相差不大,大概tps 9300左右,故還是拿的上一個圖貼出來,諒解
接口 | tps | cpu占用 | 壓測條件 |
---|---|---|---|
test1 | 9300左右 | 90%左右 | 并發200,持續壓測 |
test2 | 9200左右 | 90%左右 | 并發200,持續壓測 |
進一步得到的結論是try catch 后性能和正常返回代碼性能相當,相差無幾,可以忽略不計
2.2 最終結論
- 異常和正常代碼性能旗鼓相當,但是全局過濾器對性能影響比較大,大概降低了60%左右,全局過濾器走了管道,但是這跟微軟官方的性能優化又有沖突,想必微軟官方也是出于對全局過濾器異常處理的考慮吧。同時對于添加了業務的情況下,這個降低會被稀釋,沒去做壓測對比哈,正常用戶體量還不至于被這個給影響到穩定性。所以怎么取舍看自己
- 這里不否定使用 全局過濾器進行業務自定義異常捕獲,是否最外層try catch 掉還是全局過濾器去捕獲處理,自己根據復雜度和性能兩者中自行取舍,至少全局過濾器處理異常從性能角度上來說不是優雅的解決方式
- 對于非自定義異常,盡量按照微軟官方建議
- 使用 “測試者-執行者”模式
- “嘗試-分析”模式
最后拋出一個待求證的問題
- 疑問一:大量拋出非自定義異常,性能和正常返回性能對比會如何?比如字符串轉換int 不使用TryParse 去轉換
以上結論個人壓測結果,如有不對,歡迎交流糾正?
參考文獻
https://docs.microsoft.com/zh-cn/dotnet/standard/design-guidelines/exceptions-and-performance
https://docs.microsoft.com/zh-cn/aspnet/core/performance/performance-best-practices?view=aspnetcore-6.0
原文鏈接:https://www.cnblogs.com/jlion/p/16365572.html
相關推薦
- 2022-03-27 .NET?Core利用動態代理實現AOP(面向切面編程)_實用技巧
- 2022-10-28 Swift類和對象的底層探索分析_Swift
- 2022-07-03 python使用pandas讀xlsx文件的實現_python
- 2022-09-26 將Tomcat注冊為系統服務
- 2022-09-30 LeetCode189輪轉數組python示例_python
- 2022-10-14 DateUtil日期工具類
- 2022-07-31 python中fastapi設置查詢參數可選或必選_python
- 2022-07-30 Python?excel合并居中值相同的單元格實例代碼_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支