浅析.net core 抛异常对性能影响

目录
  • 一、前言
  • 二、求证
    • 2.1 使用.net 6 建立了一个简单的web api 项目 新增两个压测接口api接口代码如下
    • 2.2 最终结论
  • 参考文献

异常和正常代码性能旗鼓相当,但是全局过滤器对性能影响比较大,大概降低了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

到此这篇关于.net core 抛异常对性能影响的求证之路的文章就介绍到这了,更多相关.net core 抛异常性能影响内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • .NET core高性能对象转换示例代码

    前言 NET Core(开放源代码,跨平台,x-copy可部署等)有许多令人兴奋的方面,其中最值得称赞的就是其性能了.关于对象转换已经有不少轮子(AutoMapper,TinyMapper) .出于项目需要,手动造一个简单轮子.下面话不多说了,来一起看看详细的介绍吧. 示例代码 g>1.采用静态泛型类缓存,避免了拆箱装箱操作. 2.对于转换对象中有,字段名一样但是类型不一样的类时仍可以用 public static class Mapper<TSource, TTarget> where

  • ASP.NET Core异常和错误处理(8)

    在这一章,我们将讨论异常和错误处理.当 ASP.NET Core应用程序中发生错误时,您可以以各种不同的方式来处理.让我们来看看通过添加一个中间件来处理异常情况,这个中间件将帮助我们处理错误. 要模拟出错,让我们转到应用程序,运行,如果我们只是抛出异常的话,看看程序是如何运转转的. using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; using Microsoft

  • .Net Core内存回收模式及性能测试对比分析

    .NET Core 两种GC模式: Server GC / Workstation GC Server GC : 主要应用于多处理器系统,并且作为ASP.NET Core宿主的默认配置.它会为每个处理器都创建一个GC Heap,并且会并行执行回收操作.该模式的GC可以最大化吞吐量和较好的收缩性.这种模式的特点是初始分配的内存较大,并且尽可能不回收内存,进行回收用时会很耗时,并进行内存碎片整理工作.用一句简单的话说,这个就是贪婪模式,通过尽可能多的获得内存和少回收来得到更好的性能.结果就是高内存使

  • ASP.NET Core全局异常处理

    一.前言 在程序设计中,我们会遇到各种各样的异常问题,一个好的异常处理解决方案能够帮助开发者快速的定位问题,也能够给用户更好的用户体验.那么我们在AspNetCore中该如何捕获和处理异常呢?我们以一个WebApi项目为例,讲解如何捕获和处理异常. 二.异常处理 1.异常处理 开发过ASP.NET程序的人都知道:IExceptionFilter.这个过滤器同样在AspNetCore中也可以用来捕获异常.不过,对于使用IExceptionFilter,更建议使用它的异步版本:IAsyncExcep

  • ASP.NET Core中实现全局异常拦截的完整步骤

    前言 异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概念. 全局异常处理 其实在 ASP.Net Core MVC 框架中已经有了全局异常处理的机制,你可以在一个中心化的地方使用 全局异常处理中间件 来进行异常拦截,如果不用这种中心化方式的话,你就只能在 Controller 或者 Action 作用域上单独处理,这会导致异常处理代码零散在项目各

  • .NET Core/Framework如何创建委托大幅度提高反射调用的性能详解

    前言 大家都知道反射伤性能,但不得不反射的时候又怎么办呢?当真的被问题逼迫的时候还是能找到解决办法的. 反射是一种很重要的技术,然而它与直接调用相比性能要慢很多,因此如何优化反射性能也就成为一个不得不面对的问题. 目前最常见的优化反射性能的方法就是采用委托:用委托的方式调用需要反射调用的方法(或者属性.字段). 为反射得到的方法创建一个委托,此后调用此委托将能够提高近乎直接调用方法本身的性能.(当然 Emit 也能够帮助我们显著提升性能,不过直接得到可以调用的委托不是更加方便吗?) 性能对比数据

  • ASP.NET Core 中间件的使用之全局异常处理机制

    目录 1.创建项目 2.创建全局异常过滤器 3.依赖注入全局异常处理机制 4.测试全局异常处理机制 前言: 我们经常听到"秒修复秒上线",觉得很厉害的样子. 其实不然,这只是一个调侃而已,出现问题的方式很多(逻辑漏洞.代码异常.操作方式不正确等). 我们今天来说代码异常问题怎么快速定位,减少不必要的时间浪费. 这就是今天的主题"添加全局异常处理机制"捕捉异常存储到数据库(mongodb.SqlServer.MySQL等). PS:输出txt的话不怎么友好,不是所有人

  • 浅析.net core 抛异常对性能影响

    目录 一.前言 二.求证 2.1 使用.net 6 建立了一个简单的web api 项目 新增两个压测接口api接口代码如下 2.2 最终结论 参考文献 异常和正常代码性能旗鼓相当,但是全局过滤器对性能影响比较大,大概降低了60%左右,全局过滤器走了管道,但是这跟微软官方的性能优化又有冲突,想必微软官方也是出于对全局过滤器异常处理的考虑吧.同时对于添加了业务的情况下,这个降低会被稀释,没去做压测对比哈,正常用户体量还不至于被这个给影响到稳定性.所以怎么取舍看自己 一.前言 在.net 相关技术群

  • 浅谈JAVA 异常对于性能的影响

    在对客户做技术支持时,我们常常会看到很多客户根本没意识到的异常.在消除了这些异常之后,代码运行速度与以前相比大幅提升.这让我们产生一种猜测,就是在代码里面使用异常会带来显著的性能开销.因为异常是错误情况处理的重要组成部分,摒弃是不太可能的,所以我们需要衡量异常处理对于性能影响,我们可以通过一个实验看看异常处理的对于性能的影响. 实验 我的实验基于一段随机抛出异常的简单代码.从科学的角度,这并非完全准确的测量,同时我也并不了解HotSpot 编译器会对运行中的代码做何动作.但无论如何,这段代码应该

  • JS中用try catch对代码运行的性能影响分析

    前言 之前一直没有去研究try catch对代码运行的性能影响,只是一直停留在了感觉上,正好最近开会交流学习的时候,有人提出了相关的问题.借着周末,正好研究一番. 前端线上脚本错误的捕获方法: window.JSTracker=window.JSTracker||[]; try{ //your code }catch(e){ JSTracker.push(e); throwe;//建议将错误再次抛出,避免测试无法发现异常 } 设计实验方式 简单的设计方案也就是对比实验. 空白组1:[无 try

  • Android跨进程抛异常的原理的实现

    今天接到了个需求,需要用到跨进程抛异常. 怎样将异常从服务端抛到客户端 也就是说在Service端抛出的异常需要可以在Client端接收.印象中binder是可以传异常的,所以aidl直接走起: // aidl文件 interface ITestExceptionAidl { boolean testThrowException(); } // service端实现 public class AidlService extends Service { @Nullable @Override pu

  • Python 解决中文写入Excel时抛异常的问题

    近期接到业务部门需求,需将统计结果每日发送到业务部门,在调试python脚本的时候,导出的Excel标题为中文,总是抛出以下异常 Traceback (most recent call last): File "totalpx.py", line 99, in <module> export() File "totalpx.py", line 54, in export workbook.save(out_path) File "/usr/li

  • 探究C#访问null字段会抛异常原因

    目录 一:举例说明 二:异常原理分析 三:总结 一:举例说明 namespace ConsoleApp2 { internal class Program { static Person person = null; static void Main(string[] args) { var age = person.age; Console.WriteLine(age); } } public class Person { public int age; } } 由于 person 是一个 n

  • 浅谈redis key值内存消耗以及性能影响

    一.redis key数量为1千万时. 存储value为"0",比较小.如果value较大,则存储内存会增多 redis key数量为一千万时,使用了865M的内存. # Keyspace db0:keys=11100111,expires=0,avg_ttl=0 内存使用情况 # Memory used_memory:907730088 used_memory_human:865.68M used_memory_rss:979476480 used_memory_rss_human:

  • 解析后台进程对Android性能影响的详解

    Android现在这么火,各种的设备也是琳琅满目,高中低等,大小屏幕都有,但是它始终未能达到iOS那样的令人称赞的卓越体验和性能,其操作的流畅度,性能和安全性方面总是略输iOS一筹.据说iPhone4虽然是单核512M内存,但是比Android的双核1G内存的操作起来更流畅,iPad2虽然是也只有512M的内存但是操作起来比Android四核1G内存还要流畅.另外在安全性方面也不如iOS. 造成Android性能,待机时间,操作流畅和安全性不好的原因是Android后台进程的管理. Androi

  • 浅析.Net Core中Json配置的自动更新

    Pre 很早在看 Jesse 的 Asp.net Core快速入门 的课程的时候就了解到了在Asp .net core中,如果添加的Json配置被更改了,是支持自动重载配置的,作为一名有着严重"造轮子"情节的程序员,最近在折腾一个博客系统,也想造出一个这样能自动更新以Mysql为数据源的ConfigureSource,于是点开了AddJsonFile这个拓展函数的源码,发现别有洞天,蛮有意思,本篇文章就简单地聊一聊Json config的ReloadOnChange是如何实现的,在学习

  • springboot自定义拦截器的方法

    拦截器应该分属于web框架的组件,每个框架提供的自己的支持,实现方式也就不同.例如Struts和Spring,以下是Spring 的拦截器总结,它是基于动态代理(反射)实现的. Spring 中声明拦截器需要实现 HandlerInterceptor 接口,当然也可以通过继承HandlerInterceptorAdapter 抽象类,HandlerInterceptorAdapter也是实现了HandlerInterceptor 接口. 拦截器中有四个方法: preHandle:在Control

随机推荐