加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

在ASP.NET网站上锁定车队

发布时间:2020-12-16 07:42:08 所属栏目:asp.Net 来源:网络整理
导读:TL; DR: 为性能进行重构,网站变慢了.在并发可视化器中,该图看起来像MSDN上描述的 lock convoys. 上下文 我正在帮助重构ASP.NET网站以切换用户控件,使其无法在数据集上执行业务逻辑,从而在业务对象上执行表示逻辑,还可以减少用户控件的数据库调用. 问题 我们
TL; DR:
为性能进行重构,网站变慢了.在并发可视化器中,该图看起来像MSDN上描述的 lock convoys.

上下文

我正在帮助重构ASP.NET网站以切换用户控件,使其无法在数据集上执行业务逻辑,从而在业务对象上执行表示逻辑,还可以减少用户控件的数据库调用.

问题

我们已经注意到在引入涉及我们认为在多个领域中的性能改进的变化之后,性能显着下降(挂起/阻塞).

我们使用精益哨兵来监控我们网站的表现.根据挂起诊断,当GC运行时,线程池的线程用完(并根据诊断页面上的描述),它会阻止创建更多线程.根据内存诊断,GC Heap和Gen 0消耗了大量内存(约9GB).

到目前为止我做了什么?

>我在Visual Studio中使用了内存分析器,并发现了我们过多的DataAdapter和DataTable用法的问题.内存消耗降至3GB,但这仅对GC阻塞有帮助.它仍然比我们引入更改之前的速度慢,但我仍然看到由CompilationLock.GetLock()和BuildManager.GetBuildResultFromCacheInternal()等函数引起的高负载阻塞.谷歌搜索他们没有返回任何有用的东西.
>这是一个使用JIT编译的网站.我曾经认为CompilationLock的问题可能是因为JIT编译并且想要运行预编译的网站,但是我们的一个全局Utilities类引起了一些我不知道的其他Utilities类/命名空间的歧义.我发现有一个Microsoft.Build.Utilities命名空间,但它没有在我们的网站中引用,当我自己引用Microsoft.Build时,我无法重现我自己环境中的歧义,所以我无法得到在登台服务器上运行预编译模式的网站来测试这个理论.
>我使用Visual Studio的内存分配和检测分析器作为度量,对内存分配和数据库调用量进行了其他更改,但我没有注意到性能方??面的任何进展.
>我使用并发分析器来收集有关线程利用率的更多信息.我之前没有使用过这个工具,所以我不确定我的解释.每个句柄中有多个线程,在一个句柄中我看到42%的争用.我看到DataAdapter.Fill和SqlHelper.ExecuteReader方法在设置为“Show Just My Code”时显示最多,而WaitForSingleObjectExImplementation在设置为“Show All Code”时显示最多.
>我遇到了a SO question about ASP.NET websites’ performance issues并为每个页面设置了EnableSessionState =“ReadOnly”,但我也没有注意到这个变化的区别.
> Concurrency Visualizer和Common Patterns for Poorly-Behaved Multithreaded Applications帮我确定了问题.我的图表看起来不像是串行执行,但我看到了80-90%的同步,如Lock Convoys图所示.我也检查了a SO question on lock convoys debugging.

测试方法

我正在使用Screaming Frog来抓取网站,以便重现问题,并将Screaming Frog和Lean Sentry中的每秒请求数和响应时间作为性能指标.它可能不是最好的方式,但差异是明显的,可重复的,而且这几乎就是我所拥有的.

网站的体系结构

该网站最初大约10年前在VB.NET for .NET Framework 1.0中编码,并通过修复一些兼容性问题升级到.NET Framework 4.6.1.到目前为止,还没有任何架构变化.有一个共享的SqlHelper类,它是一个共享数据访问函数的集合,如ExecuteDataset或ExecuteDatareader,它返回DataSet,DataReader或String值.这些函数从web.config文件中读取连接字符串信息,并创建新的SqlConnection,SqlDataAdapter,SqlDataReader和SqlCommand对象以执行数据库操作.使用此共享类的数据访问层由每个模块(如购物车,类别,产品等)的类组成,这些类将在每个用户控件中实例化,并且它们由表示数据库中存储过程的函数组成.

重构

我们已经在相关用户控件的页面加载内部或者在转发器的OnItemDataBound事件内部引入了一些要实例化的新对象,并附加到其子用户控件的公共属性,这些属性被重构为使用该对象.但是,还有其他子用户控件需要多个数据表,因此我们决定将其中一个数据表存储在其中一个对象中,并通过将其分配给其公共属性将其传递给相关的用户控件.

我想我们通过引入这些对象来损害性能.即使数据库调用和内存消耗似乎减少了,我想知道对象是否导致线程一直被同步.

任何重构发生之前的图形:

我提到的所有重构应用后的图形:

你能帮我辨认一下这个问题吗?

解决方法

你的问题相当复杂.我认为您有两个基本选项可以解决您的重构性能问题:

>将代码更改恢复到尚未完成所有或大部分重构的时间点,以及当您的性能比当前遇到的更好时.然后,逐步添加新类以提高性能.如果更改未提高性能,则撤消它并尝试其他操作.
>使用支持接口但缺乏性能开销的版本替换部分/大部分新添加的类.有选择地这样做可以隔离存在性能问题的位置.也许,该网站已经开发了一个未知的性能错误,这个错误不是由之前实现的添加类触发的.

我赞成选项1,虽然它可能会适得其反.这有点像美式足球.当然,开车下山很不错.但有时候主导策略是踢球,让球回来并尝试在另一个驱动器上得分.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读