ntdll 异常代码0xc0000374_不要把异常当做业务逻辑,这性能可能你无法承受

一:背景

1. 讲故事

在项目中摸爬滚打几年,应该或多或少的见过有人把异常当做业务逻辑处理的情况(┬_┬),比如说判断一个数字是否为整数,就想当然的用try catch包起来,再进行 int.Parse,如果抛异常就说明不是整数,简单粗暴,也不需要写正则或者其他逻辑,再比如一个字符串强制转化为Enum,直接用Enum.Parse,可能是因为对异常的开销不是特别了解,这种不好的使用习惯也许被官方发现了,后续给我们补了很多的Try前缀的方法,比如:int.TryParse , Enum.TryParse, dict.TryGetValue ,用代码展示如下:

            //原始写法            var num = int.Parse("1");            //使用try方式            var result = 0;            var b = int.TryParse("1", out result);

用Try系列方法没毛病,但这写法让人吐槽,还要单独定义result变量,没撤,官方还得靠我们这些开发者给他们发扬光大,终于在C# 7.0 中新增了一个 out variables 语法糖。

            //try out 变量模式            var c = int.TryParse("1", out int result2);

这种 out 变量 模式就了,一个方法获取两个值,还没有抛异常的风险。

二:为什么要用tryxxx方法

有了tryxxx方法之后,你就应该明白微软已经在提醒我们开发人员不要滥用异常,尤其在可预知可预见的场景下,毕竟他们知道异常的开销真的是太大了,不知者不怪哈。

1. 肉眼看得见的低性能

为了让大家肉眼能看见,我们就用异常方法和tryxxx方法做一个性能比较,迭代50w次,看看各自的性能如何?

            for (int i = 0; i < 3; i++)            {                var watch = Stopwatch.StartNew();                for (int k = 0; k < 50000; k++)                {                    try                    {                        var num = int.Parse("xxx");                    }                    catch (Exception ex) { }                }                watch.Stop();                Console.WriteLine($"i={i + 1},耗费:{watch.ElapsedMilliseconds}");            }            Console.WriteLine("---------------------------------------------");            for (int i = 0; i < 3; i++)            {                var watch = Stopwatch.StartNew();                for (int k = 0; k < 50000; k++)                {                   var num = int.TryParse("xxx", out int reuslt);                }                watch.Stop();                Console.WriteLine($"i={i + 1},耗费:{watch.ElapsedMilliseconds}");            }            Console.ReadLine();
14bc99f279ca3ff059a4a12f29a6fb84.png

看结果还挺吓人的,相差480倍, 好熟悉的一个数字。。。 南朝四百八十寺,多少楼台烟雨中

三: 异常的超强开销

为什么异常有那么大的开销? 只有知己知彼才能心中有数,看过我多线程视频的朋友应该知道,线程的创建和销毁代价都是非常大的,其中有一项就是需要代码从用户态切换到了内核态,毕竟线程是操作系统层面的事情,和你CLR无关,CLR只是做了一层系统包装而已,其实很多人都想不到,我们用的 try catch finally 底层也是封装了操作系统层面的(Windows 结构化异常处理),也叫做SEH,什么意思? 就是当你throw之后,代码需要从用户态切换到内核态,这个开销是不会小的,还有一个开销来自于Exception中的StackTrace,这里面的值需要从当前异常的线程栈中去抓取调用堆栈,栈越深,开销就越大。

1. 从用户态到内核态

大家肯定会说,甭那么玄乎,凡事都要讲个证据, Do more,Talk less, 这里我准备分两种情况讲解。

<1> 有catch情况

准备在catch的时候阻塞住,然后抓它的dump文件。

        public static void Main(string[] args)        {            try            {                var num = int.Parse("xxx");            }            catch (Exception ex)            {                Console.WriteLine(ex.Message);                Console.ReadLine();            }        }

使用 !dumpstack 把当前 0号线程 的所有托管和非托管堆栈全部打出来,简化后如下:

0:000> ~0sntdll!NtReadFile+0x14:00007fff`f805aa64 c3              ret0:000> !dumpstackOS Thread Id: 0x2bf0 (0)Current frame: ntdll!NtReadFile+0x14Caller, Callee(MethodDesc 00007fffde3a40b8 +0x18 System.Console.ReadLine())(MethodDesc 00007fff810d59f8 +0xa5 ConsoleApp4.Program.Main(System.String[])), calling (MethodDesc 00007fffde3a40b8 +0 System.Console.ReadLine())00000044433fc700 00007fffe07a29e0 clr!ExceptionTracker::CallCatchHandler+0x9c, calling clr!ExceptionTracker::CallHandlerclr!ClrUnwindEx+0x40, calling ntdll!RtlUnwindExntdll!RtlRaiseException+0x4e, calling ntdll!RtlpCaptureContextclr!IL_Throw+0x114, calling clr!RaiseTheExceptionInternalOnly(MethodDesc 00007fffde4f95c0 System.Number.StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean)), calling mscorlib_ni+0x53976a(MethodDesc 00007fffde3b5330 +0xae System.Number.ParseInt32(System.String, System.Globalization.NumberStyles, System.Globalization.NumberFormatInfo)), calling (MethodDesc 00007fffde4f95c0 +0 System.Number.StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean))(MethodDesc 00007fffde1ebfa8 +0x2eb System.Globalization.NumberFormatInfo..ctor(System.Globalization.CultureData)), calling (MethodDesc 00007fffde1eba68 +0 System.Globalization.CultureData.GetNFIValues(System.Globalization.NumberFormatInfo))(MethodDesc 00007fff810d59f8 +0x49 ConsoleApp4.Program.Main(System.String[])), calling (MethodDesc 00007fffde3b1708 +0 System.Int32.Parse(System.String))

因为是堆栈,所以执行流就要从后往前看,你会发现流程大概是这个样子 int.Parse -> CLR -> ntdll -> CLR -> Console.ReadLine ,很显然 ntdll.dll 是操作系统层级的一个核心文件,这就从用户态切入到了内核态,如果不是很明白,我画一张简图吧。。。

ee6c2f40c0be199185ac70841afd63f3.png

<2>. 无catch处理

大家肯定很好奇,如果无catch会是怎么样,大家也可以用windbg去挖一下。

        public static void Main(string[] args)        {            var num = int.Parse("xxx");        }0:000> !dumpstackOS Thread Id: 0xd68 (0)Current frame: ntdll!NtTerminateProcess+0x14Caller, Calleemscoreei!RuntimeDesc::ShutdownAllActiveRuntimes+0x285, calling KERNEL32!ExitProcessImplementationmscoreei!CLRRuntimeHostInternalImpl::ShutdownAllRuntimesThenExit+0x14, calling mscoreei!RuntimeDesc::ShutdownAllActiveRuntimesclr!EEPolicy::ExitProcessViaShim+0x9cclr!SafeExitProcess+0x9d, calling clr!EEPolicy::ExitProcessViaShimntdll!KiUserExceptionDispatch+0x53, calling ntdll!NtRaiseExceptionclr!RaiseTheExceptionInternalOnly+0x188426, calling clr!EEPolicy::HandleFatalErrorclr!IL_Throw+0x45, calling clr!LazyMachStateCaptureState(MethodDesc 00007fffde4f95c0 System.Number.StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean)), calling mscorlib_ni+0x53976a(MethodDesc 00007fffde3b5330 +0xae System.Number.ParseInt32(System.String, System.Globalization.NumberStyles, System.Globalization.NumberFormatInfo)), calling (MethodDesc 00007fffde4f95c0 +0 System.Number.StringToNumber(System.String, System.Globalization.NumberStyles, NumberBuffer ByRef, System.Globalization.NumberFormatInfo, Boolean))(MethodDesc 00007fffde1ebfa8 +0x2eb System.Globalization.NumberFormatInfo..ctor(System.Globalization.CultureData)), calling (MethodDesc 00007fffde1eba68 +0 System.Globalization.CultureData.GetNFIValues(System.Globalization.NumberFormatInfo))(MethodDesc 00007fff810e59f8 +0x37 ConsoleApp4.Program.Main(System.String[])), calling (MethodDesc 00007fffde3b1708 +0 System.Int32.Parse(System.String))

可以看到进程的退出逻辑给了托管程序入口 mscoreei.dll 而再也没有进入Main函数了, 为此我也补一张图给大家看看

2fab24ae3c168a6005775a6f4b20dc9f.png

2. 抓取线程调用栈

当大家慌慌张张的看到异常的时候,第一眼会去看异常信息是什么? 第二眼会去看异常出在了哪一行代码,这就是线程的调用栈,这个信息非常重要,可以快捷的帮助我们找到问题解决问题,放在Exception的StackTrace中,先上一段代码。

    public static void Main(string[] args)        {            Run();            Console.ReadLine();        }        public static void Run()        {            var ex = new FormatException("你的格式错误啦!!!");            throw ex;        }

<1> StackTrace何时塞入的

到目前为止还没看到哪本书说到StackTrace是何时被塞入的? 由于水平有限,我也试着探测一下下。

276e1633c13c9aed7e9b32dd3715d494.png

从代码中可以看到不是在new的时候塞入的,那会是哪里呢?

<2> 从CLR中寻找答案

既然不在用户代码,那就到CLR中去看看,在windbg中用 dumpstack 去查看非托管堆栈。

0:000> !dumpstackOS Thread Id: 0x4090 (0)Current frame: ntdll!NtTerminateProcess+0x14Caller, Calleeclr!EETypeHashTable::FindItem+0x532, calling clr!NgenHashTable::PersistedBucketList::GetBucketclr!JIT_StrCns+0xd0, calling clr!HelperMethodFrameRestoreState(MethodDesc 00007fff810f5a08 +0x70 ConsoleApp4.Program.Run()), calling clr!IL_Throwclr!IL_Throw+0x45, calling clr!LazyMachStateCaptureState(MethodDesc 00007fff810f5a08 +0x70 ConsoleApp4.Program.Run()), calling clr!IL_Throw(MethodDesc 00007fff810f59f8 +0x28 ConsoleApp4.Program.Main(System.String[])), calling 00007fff81200488 (stub for ConsoleApp4.Program.Run())

从简化后的流程看,怀疑是由 clr!HelperMethodFrameRestoreState 处理的,为什么这么说呢? 因为我们定义的 FormatException ex 会传给CLR的,不信可以用 kb 看一看。

0:000> kb # RetAddr           : Args to Child                                                           : Call Site00 00007fff`e07a3181 : 00000000`e0434352 0000006d`4a7fe938 0000017b`30ad2d48 0000017b`2f081690 : KERNELBASE!RaiseException+0x6801 00007fff`e07a45f4 : ffffffff`fffffffe 0000017b`2ef02542 00000000`0000000a 0000017b`2f040910 : clr!RaiseTheExceptionInternalOnly+0x31f02 00007fff`811d0950 : 00000000`70000001 00007fff`810c4140 0000006d`4a7fedb8 0000006d`4a7fec78 : clr!IL_Throw+0x11403 00007fff`811d08b8 : 0000017b`30ad2d30 00007fff`810c4140 00000000`00000000 00007fff`00000000 : 0x00007fff`811d095004 00007fff`e0736c93 : 0000017b`30ad2d30 00007fff`810c4140 00000000`00000000 00007fff`00000000 : 0x00007fff`811d08b805 00007fff`e0736b79 : 00000000`00000000 00007fff`e0737aae 0000006d`4a7fefb8 00000000`00000000 : clr!CallDescrWorkerInternal+0x8306 00007fff`e0737410 : 0000006d`4a7fefb8 0000006d`4a7ff048 0000006d`4a7feeb8 00000000`00000001 : clr!CallDescrWorkerWithHandler+0x4e07 00007fff`e08dcaf2 : 0000006d`4a7fee00 00000000`00000001 00000000`00000001 0000017b`2efcecf0 : clr!MethodDescCallSite::CallTargetWorker+0x10208 00007fff`e08dd4b3 : 00000000`00000001 00000000`00000000 0000017b`30ad2d30 0000017b`30ad2d30 : clr!RunMain+0x25f09 00007fff`e08dd367 : 0000017b`2f040910 0000006d`4a7ff420 0000017b`2f040910 0000017b`2f082770 : clr!Assembly::ExecuteMainMethod+0xb70a 00007fff`e08dccb3 : 00000000`00000000 0000017b`2ef00000 00000000`00000000 00000000`00000000 : clr!SystemDomain::ExecuteMainMethod+0x6430b 00007fff`e08dcc31 : 0000017b`2ef00000 00007fff`e08de090 00000000`00000000 00000000`00000000 : clr!ExecuteEXE+0x3f0c 00007fff`e08de0a4 : ffffffff`ffffffff 00007fff`e08de090 00000000`00000000 00000000`00000000 : clr!_CorExeMainInternal+0xb20d 00007fff`e1208a61 : 00000000`00000000 00007fff`00000091 00000000`00000000 0000006d`4a7ff9f8 : clr!CorExeMain+0x140e 00007fff`e133a4cc : 00000000`00000000 00007fff`e08de090 00000000`00000000 00000000`00000000 : mscoreei!CorExeMain+0x1120f 00007fff`f5cc4034 : 00007fff`e1200000 00000000`00000000 00000000`00000000 00000000`00000000 : MSCOREE!CorExeMain_Exported+0x6c10 00007fff`f8033691 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x1411 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21

其中第一行的 00 00007fffe07a3181 : 00000000e0434352 0000006d4a7fe938 0000017b30ad2d48 0000017b2f081690 : KERNELBASE!RaiseException+0x68中的第三个参数地址0000017b30ad2d48` 就是我们的异常类,打印出来看一下。

0:000> !do 0000017b30ad2d48Name:        System.FormatExceptionMethodTable: 00007fffde285c38EEClass:     00007fffde3930e0Size:        160(0xa0) bytesFile:        C:WINDOWSMicrosoft.NetassemblyGAC_64mscorlibv4.0_4.0.0.0__b77a5c561934e089mscorlib.dllFields:              MT    Field   Offset                 Type VT     Attr            Value Name00007fffde2059c0  40002a2        8        System.String  0 instance 0000017b30ad4c80 _className00007fffde282a50  40002a3       10 ...ection.MethodBase  0 instance 0000000000000000 _exceptionMethod00007fffde2059c0  40002a4       18        System.String  0 instance 0000000000000000 _exceptionMethodString00007fffde2059c0  40002a5       20        System.String  0 instance 0000017b30ad2de8 _message00007fffde2883d8  40002a6       28 ...tions.IDictionary  0 instance 0000000000000000 _data00007fffde205b70  40002a7       30     System.Exception  0 instance 0000000000000000 _innerException00007fffde2059c0  40002a8       38        System.String  0 instance 0000000000000000 _helpURL00007fffde205dd8  40002a9       40        System.Object  0 instance 0000017b30ad2e98 _stackTrace00007fffde205dd8  40002aa       48        System.Object  0 instance 0000017b30ad2f28 _watsonBuckets00007fffde2059c0  40002ab       50        System.String  0 instance 0000000000000000 _stackTraceString00007fffde2059c0  40002ac       58        System.String  0 instance 0000000000000000 _remoteStackTraceString00007fffde2085a0  40002ad       88         System.Int32  1 instance                0 _remoteStackIndex00007fffde205dd8  40002ae       60        System.Object  0 instance 0000000000000000 _dynamicMethods00007fffde2085a0  40002af       8c         System.Int32  1 instance      -2146233033 _HResult00007fffde2059c0  40002b0       68        System.String  0 instance 0000000000000000 _source00007fffde2831f8  40002b1       78        System.IntPtr  1 instance                0 _xptrs00007fffde2085a0  40002b2       90         System.Int32  1 instance       -532462766 _xcode00007fffde21e720  40002b3       80       System.UIntPtr  1 instance                0 _ipForWatsonBuckets00007fffde1f5080  40002b4       70 ...ializationManager  0 instance 0000017b30ad2e18 _safeSerializationManager00007fffde205dd8  40002a1      100        System.Object  0   shared           static s_EDILock                                 >> Domain:Value  0000017b2efe0af0:NotInit  <<0:000> !do 0000017b30ad2e98Name:        System.SByte[]MethodTable: 00007fffde20dde8EEClass:     00007fffde390920Size:        120(0x78) bytesArray:       Rank 1, Number of elements 96, Type SByte (Print Array)Content:     .........../{...P.......@..Jm....Z.........................Jm....Y..............................Fields:None

此时 _stackTrace 已经有值了,毕竟Console上已经打印出来了。

34ed1113bef4a29709b6718d26954b74.png

最后补充一下大家也可以通过 !threads 去找异常的线程,如下图的中 System.FormatException 0000017b30ad2d48,然后通过 !printexception 去打印这个地址 0000017b30ad2d48 上异常对象。

0:000> !threadsThreadCount:      2UnstartedThread:  0BackgroundThread: 1PendingThread:    0DeadThread:       0Hosted Runtime:   no                                                                                                        Lock         ID OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception   0    1  80c 0000016816f508f0    2a020 Preemptive  0000016818CCE3B8:0000016818CCFFD0 0000016816ef0b10 0     MTA System.FormatException 0000017b30ad2d48   6    2 12d8 0000016816f7b0e0    2b220 Preemptive  0000000000000000:0000000000000000 0000016816ef0b10 0     MTA (Finalizer) 0:000> !printexception 0000017b30ad2d48Exception object: 0000017b30ad2d48Exception type:   System.FormatExceptionMessage:          你的格式错误啦!!!InnerException:   StackTrace (generated):    SP               IP               Function    0000001F8F7FEE90 00007FFF811E0951 ConsoleApp4!ConsoleApp4.Program.Run()+0x71    0000001F8F7FEEE0 00007FFF811E08B9 ConsoleApp4!ConsoleApp4.Program.Main(System.String[])+0x29StackTraceString: HResult: 80131537

三:总结

不要把异常当做业务逻辑处理,这开销有可能你承受不起,把那些真正不可期的情况留给异常吧,如: TimeoutException。。。

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

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

相关文章

java中的hashset_Java中的HashSet

java中的hashset介绍&#xff1a; Java中的HashSet实现Set接口&#xff0c;即它不允许重复。 它在内部由HashMap支持&#xff0c;该哈希表基于哈希原理。 我们可以在HashSet中存储一个空值。 默认容量为16&#xff0c;负载系数为0.75&#xff0c;其中&#xff1a; Load facto…

win32bridge.server.exe函数不正确_修电脑?不,其实我们学的是......

COMPUTER计信学子Python?JAVA?C?C?HTML?身为重师计信人逢年过节总免不了被亲戚们“盘问”一番必问清单第一名就是“专业”他们往往从字面去理解而我们计信人被误解的频率相当高“学计算机的肯定会修电脑对吧”请接着看下去吧!我们学的到底是什么&#xff1f;(点击查看答案…

SimpleDateFormat详解

SimpleDateFormat 中的时间标识含义&#xff1a; G 年代标志符 y 年 M 月 d 日 h 时 在上午或下午 (1~12) H 时 在一天中 (0~23) m 分 s 秒 S 毫秒 E 星期 D 一年中的第几天 F 一月中第几个星期几 w 一年中第几个星期 W 一月中第几个星期 a 上午 / 下午 标记符 k 时 在一天中 …

java uuid_Java UUID

java uuid介绍&#xff1a; UUID&#xff08;通用唯一标识符&#xff09;表示一个128位长的唯一值 。 它也被普遍称为GUID&#xff08;全球唯一标识符&#xff09;。 UUID的标准表示形式由十六进制数字组成&#xff1a; 533a4559-e55c-18b3-8456-555563322002并具有36个字符 …

JDK 9.0.4 报错:程序包 com.sun.xml.internal.fastinfoset.stax.events 不存在/不可见

IDE&#xff1a;IntelliJ IDEA 构建工具&#xff1a;Maven JDK版本&#xff1a;JDK 9.0.4 在代码中使用下面的工具类&#xff1a; com.sun.xml.internal.fastinfoset.stax.events.Util报错如下&#xff1a; 或者 光标移到 Util 处&#xff0c;按下 Option Enter&#xff1a…

3650m5设置u盘启动_系统重装必备神器,U盘如何制作启动盘?

早些年的时候&#xff0c;电脑安装系统需要光盘&#xff0c;但是现在光盘也逐渐退出历史舞台。不管是台式计算机还是笔记本&#xff0c;光驱这个东西也逐渐消失。如果自己的计算机没有光驱&#xff0c;电脑又无法开机需要重装系统&#xff0c;这个时候该怎么办呢&#xff1f;可…

jtable隐藏全部_全部隐藏!

jtable隐藏全部在较早的文章中 &#xff0c;我写了以下几句话&#xff1a; 在面向对象的代码库中&#xff0c;该工具包应尽可能离散。 您使用开发套件的次数越多&#xff0c;您的代码实际面向对象的次数就越少&#xff0c;或者您的抽象并不是最好的。 。 我认为有必要详细说明…

IntelliJ IDEA 如何多模块开发

参考&#xff1a; https://blog.csdn.net/jqc874789596/article/details/86609554

距离矢量路由算法的java代码_八大排序算法比较(附Java代码)

冒泡排序/*** 冒泡排序 比较好理解* 两两相比 较大的放后面* 时间复杂度O(n^2)*//*** 改进前的冒泡排序算法进行100,000数据排序运行时间为&#xff1a;3829ms* 优化后的冒泡排序算法进行100,000数据排序运行时间为&#xff1a;3551ms*/ public static void bubbleSort(int[] a…

jaxb注解使用_使用JAXB时

jaxb注解使用并没有很多例子可以说明这一点&#xff0c;但是如何在应用程序中使用JAXB可以在性能&#xff08;和内存使用&#xff09;方面产生巨大差异。 这个例子 在此博客文章中&#xff0c;我将使用一个名为Membership的示例对象&#xff0c;看起来像这样&#xff1a; 我们…

org.apache.tomcat.util.descriptor.web.WebXml.setVersion 未知版本字符串 [4.0]

参考&#xff1a; https://blog.csdn.net/qq_40829288/article/details/93936261 https://www.shuzhiduo.com/A/Ae5RnvaN5Q/ https://www.cnblogs.com/youpeng/p/11095504.html

python无法安装pycurl_Python安装pycurl失败的解决方法

Centos安装pycurlcentos 安装pycurlyum install python-devel curl-develpip3 install pycurlMac(老版本)安装pycurl解决MacOS升级后出现xcrun: error: invalid active developer path, missing xcrun的问题xcode-select --install然后dongchang-5:qqmusic baoshan$ pip3 insta…

组装一台计算机 java_如何在同一台计算机上安装多个Java版本

组装一台计算机 java一段时间以前&#xff0c;我写了一篇文章《 用示例解释Java Lambda表达式》&#xff0c;但是我很容易浏览Java 8&#xff0c;因为我在项目中使用了Java 8&#xff0c;并且允许我安装和使用它。 但是在我当前的项目中&#xff0c;我们仍在使用Java 8&#xf…

字符串类型的日期如何存储到数据表Date类型的字段中

在使用 JDBC 访问数据库存储数据时&#xff0c;日期类型的数据必须是 java.sql.Date 的才能注入到 SQL 语句中。 因此这里是将字符串类型的日期转换成 java.util.Date&#xff0c;接着再转换成 java.sql.Date &#xff0c;最后注入到 SQL 语句中。 public class ProjectDAO { …

python执行linux命令返回结果_python执行linux命令的简单示例

对python执行linux命令的两种方法感兴趣的小伙伴&#xff0c;下面一起跟随编程之家 jb51.cc的小编两巴掌来看看吧&#xff01;python执行linux命令有两种方法&#xff1a;在此以Linux常用的ls命令为例&#xff1a;方法一&#xff1a;使用os模块shell# python>> import os…

web api开启错误提示_当HTTP状态代码不足时:处理Web API错误报告

web api开启错误提示RESTful Web API设计的一个领域&#xff08;经常被忽视&#xff09;是如何报告与业务或应用程序有关的错误和问题。 首先要想到HTTP状态代码的正确用法&#xff0c;尽管非常方便&#xff0c;但通常它的信息量还不够。 让我们以400错误请求为例。 是的&#…

会议室分配时间最长_论文导论动态任务分配GPU上图计算的高效处理方式

编者按GPU作为一种硬件&#xff0c;相比较于CPU来说&#xff0c;有更多的并行度和更高的带宽&#xff0c;在图像处理领域取得了非常好的应用效果。越来越多的研究也正试图将GPU也应用到图计算领域中&#xff0c;然而GPU适合进行规则运算&#xff0c;但是图是一种不规则的数据表…

JS(Javascript)校验表单项的内容是否合规

<script !src"">/*** 分析&#xff1a;* 1.给表单绑定onsubmit事件* 监听器中判断每个方法检验的结果&#xff0c;如果都是true&#xff0c;则监听器方法返回true&#xff1b;如果有一个为false,* 则监听器方法返回false* 2.定义一些方法分别校验各个表单项* 3…

java \t怎么从头开始_如何从头开始以正确的面向对象方式创建Java Web Framework

java \t怎么从头开始您如何用Java设计Web应用程序&#xff1f; 您安装了Spring&#xff0c;阅读了手册&#xff0c;创建了控制器 &#xff0c;创建了一些视图&#xff0c;添加了一些注释 &#xff0c;它就可以工作了。 如果没有Spring &#xff08;Ruby中没有Ruby on Rails&…

kl散度的理解_以曲率的视角理解自然梯度优化

一个故事我要讲一个故事:一个你几乎肯定听过的故事&#xff0c;但它的侧重点与你习以为常关注的不同。所有现代深度学习模型都使用梯度下降进行训练。 在梯度下降的每个步骤中&#xff0c;您的参数值从某个起始点开始&#xff0c;然后将它们移动到最大损失减少的方向。 你可以通…