仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 695|回复: 8
打印 上一主题 下一主题

[学习教程] ASP.NET编程:下降.NET使用程序内存占用的理论和总结...

[复制链接]
小妖女 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:17:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
我觉得这个学习方法很重要。初学者应该跟我一样有同样一个毛病。那就是急于求成。很想就自己做出个小小的系统来。可真要动手,却又茫然而不知所措。为什么会这样呢?因为我们没有耐心去学习基础知识。写根本看不到什么效果的测试代码。</p>比来一周对照忙,次要的事情内容是在做一个叫“键盘精灵”的器材,复杂来说就是将良多数据放到内存中,对这些数据举行疾速检索,然后找出依据输出前提最婚配的10笔记录并予以展现。详细和上面两款炒股软件的相干功效相似:



数据以文本情势存在文件中,且数据量较年夜,有近20万条,每笔记录有几个字段,以分开符支解。事先利用的是6万笔记录的测试数据,文本文件快要10M,这个模块加载到内存并创建缓存以后,也许会占用快要70-80M的内存。自我接办今后,次要的义务就是下降内存损耗和进步婚配效力。
1、制止创立不用要的工具
拿到代码后,第一步就是看计划文档,然后断点一步一步的看代码,也许分明了逻辑以后,发明思绪有一些成绩。之前的代码处置流程思绪也许是上面如许的:
1.将文件读取到内存,实例化
2.依据前提对文件举行检索,并存储到了局集1中
3.对了局集1中的了局举行婚配度盘算,并存储到了局会合2
4.按对了局集2举行婚配度排序,取最婚配的10笔记录,然后前往
这个过程当中规中矩。可是个中有良多成绩,最年夜的成绩是,一时变量存储了太多的两头处置了局,而这些工具在一次查询完成后又即刻抛弃,大批的一时工具带来了很年夜的GC压力。举例来讲,当用户在输出框中输出1的时分,假定利用Contains来婚配,那末从6万笔记录中找出包括1的纪录大概有4万多条,然后必要把这4万多笔记录存储在一时变量中举行处置,进一步盘算这4万笔记录的婚配度,然后存储到一个相似KeyValuePair的汇合中,key为婚配度,然后对这个汇合按Key举行排序,然后取前10条最优纪录。能够看到,两头创立了大批的一时变量,使得内存剧增,大批一时工具创立以后即刻会被接纳,GC压力山年夜。
而在计划文档中,只需求前往最最婚配的10笔记录,之前的办理计划中仿佛并没有注重到这一点。以是接办后,第一步就是对下面的处置历程举行精简。精简后以下:
将文件读取到内存,实例化
依据前提对文件举行检索,假如存在,则:
盘算婚配度。
以婚配度为Key,存储到只要11个容量的SortList中。
假如SortList汇合增加纪录后年夜于10个,则移除最初面一个元素,一直坚持着前10个最小(婚配度最优)的纪录。
遍历完成以后,前往这个汇合工具
经由这一修正,削减了大批一时数据对内存的占用,全部过程当中,我只是利用一个容量为11的SortList布局存储两头的历程,每次拔出一个元素,SortList帮我们排好序,然后移除最不婚配的那一个,也就是最初一个元素(从小到年夜排序,越婚配,值越小)。这内里的损耗次要是SortList的拔出,外部排序和移除纪录。说到这里在选择SortList仍是SortDictionary的成绩上纠结了一下,因而又找了些材料,SortDictionary在外部利用红黑树完成,SortList接纳有序数组完成,在外部排序都为O(logn)的条件下,SortDictionary的O(logn)拔出及删除元素的工夫庞大度优于SortList,可是SortDictionary会比SortList占用更多内存。基础来讲这是一个查询速率和内存分派之间的均衡,因为这里只必要存储11个工具,以是二者相差不年夜。实在即便没有这类布局,本人也能够完成的,不过就是一个汇合,每次增加一个,排好序,然后将最年夜的谁人移除。.NET利用起来便利是由于有良多这些壮大的内置数据布局。



经由下面这个小小的修正,内存占用一会儿下降了1倍,从本来的70-80M,下降到了30-40M,实在这就是下降内存开支的一个最基础的准绳,那就是制止创立不用要的工具。
2、优化数据范例及算法
越到前面内存的下降愈来愈坚苦。细心看了代码以后,除下面以外,代码中也有一些其他成绩,好比,一入手下手就将大批的工具实例化到内存中,然后一向保留。每笔记录中的信息对照多,但真正有效的用于搜刮婚配的只要上面四个字段,可是全体的实例化会将其他没有效的字段也一并序列化出来了。招致良多内存被无用的字段占用。
“股票代码股票中文名中文拼音市场范例……
600000浦发银行PFYH上证A股……”
以是第一步就是在内存中只寄存必要检索的下面四个关头字段,每笔记录刚入手下手是利用string[]数据,而不是利用类大概别的布局来保留,也实验利用布局提来保留,可是因为四个字段,数据量年夜,两头还要作为参数传送,以是比利用类还年夜,这里只是复杂的利用了数组。
除下面这些以外,为了进步搜刮效力,对数据依照0-9,a-z开首对数据做了切分分块缓存,如许当用户输出0时,间接从以0为key的块中读取数据,如许速率是加速了,可是大批的缓存也增添了对内存的损耗。缓存的数据基础上和加载到内存华夏始的数据一样年夜了。而且在搜刮的过程当中,也是接纳的完整搜刮,关于17万条数据的四个字段,每次查询要举行170000*4次遍历对照,才干找出最婚配的10条数据来。
为此,引进了不完整搜刮,就是事前对各种型证券,如股票,基金,债券分类,对每类按证券代码举行排序。当用户设置了搜刮的优先级时,顺次在每类中查找,假如找到满意前提的10笔记录,则当即前往,由于数据已事前依照证券范例和代码排好序了,以是前面找到的一定没有之前找到的婚配度高,这一改善间接进步了搜刮查询的效力。对有序的数据举行查找效力一样平常会比无序的数据查找效力高。我们罕见的一些查找算法,好比说,二分查找法,条件也是待查找的汇合有序分列。
3、接纳非托管代码大概模块编写数据处置逻辑
下面的两部操纵固然削减了快要50-60%的内存占用,可是仍旧达不到向导的请求,因而又实验并对照了各类利用分歧的数据布局将数据载进到内存中的内存占用巨细,包含间接将文件按范例读成字符串、数组、布局及类,内存占用最小的间接将文件读成字符串,10M的数据文件读进内存也会占用20-30M的空间,还不谈对其举行处置过程当中发生的一些一时变量对内存的占用。利用dotTrace及CLRProfile等工具反省以后,发明内存的占用也是这些原始数据。然后以”Howtoreducethememoryusageof.NETapplications”到网上搜了一下削减.NET内存占用的一些办法,在StackOverflow上看到了这一回覆:



该同砚指出.NET使用程序和其他利用当地代码编写的程序比拟会有较年夜的内存占用,假如对内存开支对照在乎,.NET大概不是最好的选择。.NET使用程序的内存必定水平上受渣滓接纳的影响。并指出,一些数据布局如List,体系会分派过剩的空间。可使用值范例而不是援用范例,不要创立年夜工具,以避免发生内存碎片等等下降内存占用的倡议。
这些都思索过以后,内存仍是达不到请求,以是入手下手寻觅挪用非托管代码的体例来本人更天真的把持内存的分派与烧毁。可是全部程序都是接纳.NET编写的,全体切换成C大概C++不实际,以是只要两种计划,一是利用unsafe代码,二是将数据加载和检索模块接纳C大概C++编写,在.NET中接纳P/Invoke手艺挪用。
刚入手下手想接纳unsafe代码,对数据的加载及检索间接在放在unsafe代码中。厥后以为代码有些乱,分歧作风的代码混同在一同不太好,并且数据加载和检索的逻辑也对照庞大。以是就间接接纳第二种计划,利用C++编写数据加载和检索逻辑。然后在.NET内里挪用。
在入手下手之前,也做了一些评价,好比将一样的10M的数据加载到内存中,都接纳字符串的体例存储,.NET中会占用20-30M的内存,而在C++中只要9-10M的模样,并且变化很小。这恰是必要的了局。
因为对C++不熟,一时抱佛脚,翻了下C++PrimierPlus中关于字符串和STL的相干章节,并哀求其他开辟小组赐与了必定的帮忙,界说了基础的接口。为了演示,我创立了两个工程,一个是名为SecuData的C++Win32DLL工程,一个是测试该类库的名为SecuDataTest的C#WinForm程序。
我在C++中界说好了4个办法,一个初始化加载数据,一个设置搜刮优先级,一个查找婚配办法和一个卸载数据办法,详细的算法因为事情缘故原由方便贴出,这里只是举一个复杂的例子,办法名及工程布局以下图:



然后再在.NET中利用P/Invoke手艺引进C++DLL中界说的办法。



如许就能够在.NET中挪用这些办法了,必要申明的是,办法的传进值这里是利用String范例的,第二个StringBuilder范例的参数是办法的真正前往值,办法的全体int型前往值标明办法是不是实行乐成。在挪用查找办法时,第二个StringBuilder参数必需初始化一个最年夜的查询了局的巨细,由于在C++中会往这个工具中写进了局,不初始化大概初始化太小城市抛出非常。固然也能够间接前往布局体,这个就必要分外界说,这里前往的都是字符串。完了本人在.NET内里对其举行剖析。
必要注重的是,调试的时分,假如必要调试C++内里的代码,必要指定DLL的天生目次及启动方针,而且将C++项目设置为启动项目,这里我设定天生DLL的目次为SecuDataTest项陌生成的SecuDataTest.exe文件地点的目次,调试启动方针设置为SecuDataTest.exe,如许在C++项目中设置断点,启动.NETWinform程序,当P/Invoke触发断点时可以慢慢调试C++代码。
在公布的时分,最好将默许的静态库设置修正为静态库,如许VS会把依附的相干C++库打包到天生的dll中,部署到客户呆板上不会呈现成绩。SecuData类库项目标属性设置以下图:



改成这类P/Invoke形式以后,10M数据载到内存中,内存占用只要10M摆布,较之前接纳.NET的30-40M的内存又下降了良多,并且内存动摇对照小,满意了对内存占用的请求。
接纳这类“混搭”体例有一些优点,既有.NET的疾速开辟,又有C++的天真的内存分派烧毁形式和代码平安性回护。在良多时分,能够将一些对内存占用对照敏感,年夜数据量的处置逻辑,放在C++中处置,使用天真的手动内存办理形式下降这部分的内存占用;将中心的数据布局及算法利用C++编写,能够进步代码的平安性,进步程序的反编译难度。
4、结语
.NET使用程序因为必要加载CLR及一些通用类库,而且具有渣滓搜集机制,较其他当地言语如C,C++具有较年夜的footprint,利用.NET创立一个复杂的Winform大概就会占用近10M的内存,以是跟着开辟的举行,内存占用会对照年夜。固然这些在良多时分是因为开辟者本身对.NET底层机制不熟习,好比在有些中央可使用值范例而利用援用范例;创立了大批的一时的周期对照短的工具;利用了过量的静态变量及成员招致内存被久长占用而得不到接纳;和.NET外部的一些机制,好比汇合工具会在外部事后分派过剩的空间等等。良多时分由于有.NET的GC机制,使得我们不用往存眷工具的烧毁而很”小气”的往创立新工具,往利用一些重型的内置工具,从而招致内存占用过年夜。办理好这些成绩,实在能够下降.NET使用程序的相称年夜一部分的不用要的内存占用。
除懂得.NET框架的一些外部机制以外,优秀的思绪,高效数据布局和算法也能够使得成绩变得复杂而削减内存的开支。
最初关于对内存请求对照敏感,能够使用C/C++的手动的天真的内存办理言语来编写响应模块,在.NET中接纳P/Invoke手艺举行挪用来削减一些内存。
以上是我对下降.NET使用程序内存占用的一点儿理论和总结,但愿对您有所匡助。
对于new隐藏成员的作用,往往是出于使用了一个第三方类库,而你又无法获得这个类库的源代码,当你继承这个类库的某个类时,你需要重新实现其中的一个方法,而又需要与父类中的函数使用同样的函数,这是就需要在自定义的子类中把那个同名函数(或成员)加上new标记,从而隐藏父类中同名的成员。
活着的死人 该用户已被删除
沙发
发表于 2015-1-19 06:49:55 来自手机 | 只看该作者
ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。
飘灵儿 该用户已被删除
板凳
发表于 2015-1-26 11:31:29 | 只看该作者
它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。
金色的骷髅 该用户已被删除
地板
发表于 2015-2-4 15:04:19 | 只看该作者
那么,ASP.Net有哪些改进呢?
兰色精灵 该用户已被删除
5#
发表于 2015-2-10 02:18:38 | 只看该作者
比如封装性、继承性、多态性等等,这就解决了刚才谈到的ASP的那些弱点。封装性使得代码逻辑清晰,易于管理,并且应用到ASP.Net上就可以使业务逻辑和Html页面分离,这样无论页面原型如何改变。
变相怪杰 该用户已被删除
6#
发表于 2015-2-28 15:34:35 | 只看该作者
ASP.NET:ASP.net是Microsoft.net的一部分,作为战略产品,不仅仅是ActiveServerPage(ASP)的下一个版本;它还提供了一个统一的Web开发模型,其中包括开发人员生成企业级Web应用程序所需的各种服务。ASP.NET的语法在很大程度上与ASP兼容,同时它还提供一种新的编程模型和结构,可生成伸缩性和稳定性更好的应用程序,并提供更好的安全保护。
因胸联盟 该用户已被删除
7#
发表于 2015-3-10 01:41:23 | 只看该作者
ASP.net的速度是ASP不能比拟的。ASP.net是编译语言,所以,当第一次加载的时候,它会把所有的程序进行编译(其中包括worker进程,还有对语法进行编译,形成一个程序集),当程序编译后,执行速度几乎为0。
莫相离 该用户已被删除
8#
发表于 2015-3-17 04:11:00 | 只看该作者
它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。
再见西城 该用户已被删除
9#
发表于 2015-3-23 19:16:49 | 只看该作者
主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 03:56

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表