.net技术原理
文章平均质量分 57
差池-BJ
1:高性能,高并发
2:技术原理
展开
-
最好不要偶遇-垃圾回收
一.问题循环调用同一个接口,调用100次,其中有95次或是98次都是几十毫秒返回,但是有那么几次一秒左右才返回。接口相同,参数相同,返回时间怎么差异这么大?这个问题困扰了我很长时间,经过一段时间的研究终于知道原因了,起初我猜测可能的原因如下:1:难道是网络问题?2:难道是缓存问题?二.分析问题1:网络延迟服务同属于一个局域网,网络延迟不会超过5ms,所以不是网络延迟造成的。2:没有命中缓存如果没有命中缓存,也应该是第一个请求没有命中,后续的请求就会从缓存中拿数据了。(我使用的缓存策略是从关系原创 2021-04-06 15:05:19 · 225 阅读 · 0 评论 -
Linq延迟执行(.Net)
调试代码的时候,突然发现Linq语句不会立即执行,当时一头雾水,因此找资料学习了一下,之后发现身边很多人都忽略了这个细节,所以把他拿出来说一下。一.特点1:Linq不会立即执行,某些操作才会触发Linq的真正执行,例如 Foreach,Count(),ToList(),ToArray() 等等。二.问题1:由于某些操作会触发Linq执行,这样会导致Linq语句的重复执行,这会比较耗费性能,特别像数据库查询这种场景。三.解决方案1:为了减少Linq重复执行的问题,先用ToXXX()这类方法转换成集原创 2020-11-21 23:16:50 · 486 阅读 · 0 评论 -
For和Foreach处理匿名函数的差别
有一天看C#本质论,突然发现For和Foreach对匿名函数处理的方式不同,差别比较隐蔽,因此想跟大家分享 一下。一.差别看代码,很简单,只有三个方法:1:Main方法,负责调用ForTest和ForeachTest方法:2:ForTest方法,包含如下内容:定义一个Action委托列表 ;通过for循环向Action列表中添加匿名函数,匿名函数用来输出变量“i”;循环Action列表,执行匿名函数;3:ForeachTest方法,包含如下内容:定义一个Action委托列表;定原创 2020-10-25 02:27:25 · 661 阅读 · 0 评论 -
windbg分析单个服务线程数很多的问题
有一天突然发现生产环境单个服务的线程数很多,如下图所示:因此我想到了两个问题,第一:为什么同时存在这么多线程?第二:线程是怎么产生的?一.为什么同时存在这么多线程?1:通过windbg分析dump文件,使用命令!threadpool查看,可以看到存在大量空闲线程:2:用命令!threads查看线程,如下图,存在大量的MTA(Threadpool worker),这样的线程就是空闲线程。切换到任意一个线程,我选择了212这个线程,用命令!dumpstack输出堆栈信息,可以看到线程最后调用的是W原创 2020-10-17 23:21:16 · 1481 阅读 · 0 评论 -
损坏状态异常--StackOverflowException导致服务挂掉
最近遇到一个问题,服务发版后,过几分钟就会挂掉,按照我以往的经验分析可能是CPU达到100%或内存不足,但是我查看了服务的状态,CPU和内存都还很充裕。此时我晕了…,通过分析dump文件,才知道是因为StackOverflowException导致服务挂掉了。那问题来了:1:是什么导致了StackOverflowException。2:为什么StackOverflowException导致服务挂掉了。一.问题1:是什么导致了StackOverflowException看代码,如下图所示:1:通过原创 2020-09-12 23:22:47 · 793 阅读 · 0 评论 -
Monitor 最底层实现原理(.Net)
经常听大家聊锁的事情,可是为什么就能锁住呢,这个问题可能10个人里面9个人不知道,今天来说明一下具体的原因。一.原理1、原理:当调用Monitor.Enter()时,CLR通过在对象头中存储当前线程ID或通过在同步块表中创建同步块并将其索引存储在对象头中来注册锁。2、下图表明了对象头、同步块表和同步块对象三者之间的关系。同步块表存储了同步块对象的引用。同步块表保存了实体对象的引用(弱引用)。对象头存储了同步块对象在同步块表中的索引。3、那什么是对象头呢,现在说明一下:对象头:狭义又称原创 2020-08-29 12:04:57 · 1536 阅读 · 7 评论 -
lock原理及使用举例(.net)
我们经常用lock加锁,实现数据操作的安全性,本篇文章将介绍lock的实现原理及几种使用方式。一.原理lock的作用是将多线程“单线程化”,从而实现多线程按照顺序执行。lock其实是一个语法糖,编译器会将lock转换成monitor,看一下中间代码便一目了然.1:c#源码2:编译后的中间码,编译器根据show方法生成了一个类<>__DisplayClass3_0,在该类中包含了一个b__0方法:如下图3:b__0方法中的代码如下图,我们看到此处用到了Monitor进行加锁:二.原创 2020-08-15 01:04:46 · 3660 阅读 · 0 评论 -
解密async await 原理(.net)
我们经常用async和await实现异步方法,那么他的实现原理是什么呢,今天介绍一下。一.代码1:介绍原理之前,先看一段简单的代码:2:代码执行结果,如下所示,想必结果和大家的预期是一样的:二.工具研究async await使用的工具是dotPeek,注意:要勾选 show compiler-generated code。下载地址:https://www.jetbrains.com/decompiler/download/#section=web-installer三.原理也许大家都听原创 2020-08-03 00:54:13 · 2690 阅读 · 2 评论 -
验证垃圾回收规则(.net)
无论通过看书或是听别人讲关于垃圾回收的事情,我们或多或少都有一些了解,但是我们了解的内容是正确的吗,今天我要做的事情就是这样,证明垃圾回收规则。垃圾回收原理简单说一下垃圾回收的基本原理:1:Clr将heap分成3个代龄区域: Gen 0、Gen 1、Gen 2。2: 采用Mark Sweep算法进行回收。3:GC触发条件:CLR检查到第0代超出预算时会触发一次GC;代码显式调用System.GC的静态Collect方法;Windows报告低内存情况;CLR正在卸装AppDomain;C原创 2020-06-21 02:01:37 · 232 阅读 · 0 评论 -
C#计算对象占用内存大小(.net)
我们写了很多的代码,但是有没有想过每写一句代码会占用多大空间呢,现在就来算一下。一.对象大小影响对象占用多大空间的主要因素如下:1:字段个数2:字段类型3:字段布局二.字段类型先来看一下,主要数据类型在32位系统和64位系统中的字节长度:从上面可以得知只有指针类型变成了8个字节,因为指针里面存储的是数据的地址,而非数据本身,所以会变为2倍。三.布局在clr中,布局一共有三种:1:LayoutKind.Auto:clr会优化字段排序。2:LayoutKind. Sequential原创 2020-06-13 10:56:56 · 8465 阅读 · 1 评论 -
在clr中,new创建对象都做了哪些操作(.net)
用了好多年的new(创建对象),可是对于new背后都做了哪些操作,一直不清楚,经过两周的研究(不仅仅是看书上的理论,还要证明书上所说的是否正确),终于明白一些,现在来说一下:工作内容每当我们用new创建一个对象时,都会做如下操作:1:计算类型的字段(以及从积累集成的字段)所需的字节数。2:加上对象开销所需字节数。类型对象指针:4字节(32位),8字节(64位);同步快索引: 4字节(32位),8字节(64位);3:clr检查区域中是否存在分配对象所需的字节。如果托管堆有足够的空间,就在原创 2020-06-06 00:51:30 · 326 阅读 · 0 评论 -
为什么return 无法跳出 foreach (.net)
我们在写代码的时候经常在foreach循环里面通过return跳出整个函数,如下所示:1:创建一个string列表,然后插入两条数据,“张三”和“李四”,通过foreach循环输出,当输出第一条数据“张三”后,执行return跳出函数,因此输出结果是:“张三”![在这里插入图片描述](https://img-blog.csdnimg.cn/20200530185855464.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shado原创 2020-05-30 19:24:25 · 1778 阅读 · 0 评论 -
何时回收线程池中空闲线程(.net)
看书或是查看资料时,都会看到类似于这样一句话:线程池大量空闲线程将在一段时间后自己醒来终止自己以释放资源。那真实的情况是这样吗,现在就来证明一下:一、代码通过代码进行验证,代码很简单,只包含三个函数,如下:1:Main()函数:记录启动程序后,最初的线程数 ;记录启动线程池后的线程数 ;记录随着时间的推移,线程数的变化;2:StartThreadpool()函数通过Task.Run()启动线程池3:GetThreadCount()函数获取进程中所有线程数二、执行结果原创 2020-05-23 19:03:08 · 1964 阅读 · 1 评论 -
线程开销(.net)
我们经常使用多线程提升程序执行速度,那是不是线程越多越好,显然答案是否定的。因为线程本身也会有不小的开销。开销主要体现在两方面:1、空间开销,2、时间开销空间开销空间开销主要体现在以下四方面:线程内核对象(thread kernel object);线程环境块(thread environment block,TEB);用户模式栈(user-mode stack);内核模式栈(kernel-mode stack);空间开销-线程内核对象1.定义:OS为系统中创建的每个线程都会分配并初始化原创 2020-05-16 00:42:52 · 597 阅读 · 0 评论 -
揭秘Dictionary实现原理
字典(Dictionary)是我们经常使用的一种数据结构,那它的实现原理是什么样的,他是怎么构成的呢,马上揭秘。物理结构Dictionary的是由两个数组和一个结构体构成:buckets数组:int数组,用来分散数据的;entries数组:entry数组,用来存储数据的;entry:存放在entries数组中,它是一个结构体,由四个属性构成:hashCode,next,key,valu...原创 2020-05-04 23:47:59 · 3126 阅读 · 0 评论 -
线程池如何管理线程
本篇介绍一下CLR中,线程池是如何管理线程的。在介绍之前,先说明下线程池的设置。一:线程池设置:一般不建议设置线程数,就像从来都不会限制程序使用的内存量,或限制使用的网络带宽。1:默认拥有的线程数大约是1000个线程。2:32位进程最多能够有大约1360个线程。3:64位进程理论上可以创建千百万个线程。二:如何管理工作者线程:我们先了解下全局对列和本地对列的区别:1:全局对列:...原创 2020-04-19 12:06:05 · 1957 阅读 · 0 评论 -
揭秘ThreadLocal(.net)
网上有很多关于ThreadLocal的文章,但是很多都是介绍java中的ThreadLocal。今天我来介绍.net中的ThreadLocal的实现原理。ThreadLocal定义1:提供数据线程的本地存储,也就是每个线程都有一个变量副本,而且互不影响。2:为了有一个直观的感受,看一段代码:3:此段代码的执行结果如下:其中,3、1代表线程号,后面的王五、李四代表这两个线程对应的各自的值...原创 2020-04-06 18:03:48 · 1108 阅读 · 0 评论 -
为什么用StringBuilder替换String
一:问题:什么时候用String,什么时候用StringBuilder?二:回答问题前,要搞清楚什么是可变类型,什么是不可变类型1:可变类型:即对象一旦被创建初始化后,它们的值可以被改变,每次都是修改原对象,不会产生新的对象。2:不可变类型:即对象一旦被创建初始化后,它们的值就不能被改变,每次修改都会产生新的对象。3:不可变类型优点:3.1:如果创建很多个相同值的字符串对象,他在内存...原创 2020-03-14 22:13:26 · 841 阅读 · 0 评论 -
.net 无法加载程序集
无法加载程序集场景:发布(启动)服务时,经常会遇到这种情况:无法加载程序集或他的依赖程序集,如下图:如何解决这种问题:第一种情况:如果对项目很熟悉,能够快速解决,因为知道 那个 程序集引用了 这个 dll,添加上引用就可以了。第二种情况:项目比较大 ,大量依赖其他团队的程序集,这样就很难判断出这个Dll到底是被哪个程序集使用。这种情况就比较难办,我来介绍一下 这种情况下的处理思路:第...原创 2019-12-28 23:50:31 · 1144 阅读 · 0 评论 -
Ref传参
一:什么是Ref传参1:让参数按照引用传递。期效果是,当控制权传递回调用方法时,在方法中对参数所做的任何修改都将反映到改变量中,也等同于将值类型的数据使用引用方式传参。若要使用Ref传参,则方法定义和调用方法都必须显示使用Ref关键字。二:代码1:没用用ref传参。输出结果是什么?结果:不会输出任何数据2:使用Ref传参,输出结果是什么?结果:输出5个张三三:为什么是这样答案:...原创 2019-10-28 23:19:22 · 1835 阅读 · 0 评论