关于占用内存的问题:为什么我的程序很小却占用 20M 内存呢?

LiaoCheng 2001-11-07 06:31:44
关于占用内存的问题:为什么我的程序很小却占用 20M 内存呢?
我使用的是VB+SQL SERVER70,数据库不到一万条记录,耗的内存怎么会那么多

有谁知道写VB时如何注意内存消耗,怎么样优化内存才会使做出来的程序占的内存少呢?
请多多发表意见或建议
多谢!!!

...全文
383 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
fangoxyz 2001-11-10
  • 打赏
  • 举报
回复
减少使用内存的最好的方法是使用VC++,在VC++里面可以非常严峻对使用内存,而且本身就有优化代码(相对于VB)和优化内存的功能。
在VB中,对不使用的数据库连接进行释放内存,不使用的窗体使用set xx=nothing 进行释放,以及对变量的定义尽量使用占用内存比较小的类型,减少对全局变量的定义
总之在VB里,整个编码都考lu到内存的使用情况且对VB的基础比较清楚的话,运行速度可加快,内存使用可以减少1/4。
hillmanweb 2001-11-07
  • 打赏
  • 举报
回复
减小代码大小


当减小应用程序的大小非常重要时,有许多技术可用于编制更紧凑的代码。除了缩小应用程序所占内存的大小外,大部分优化方法还缩小了 .exe 文件的大小。作为一种附属的优点,较小的应用程序加载得更快。

多数大小优化技术都包括从代码中删除不必要的元素。在编译应用程序时,Visual Basic 自动删除某些元素。而以下元素的长度或数量是无须限制的:

标识符名称


注释


空行
当应用程序作为一个 .EXE 文件运行时,以上这些元素都不会影响应用程序所占内存的大小。

其它元素,如变量、窗体和过程,确实要占据内存的一部分空间。最好将它们精简以使效率更高。当应用程序作为一个 .EXE 文件运行时,有几项技术可用于缩小应用程序所需内存。以下技术可缩小代码大小:

减少加载窗体的数目。


减少控件数目。


用标签代替文本框。


保持数据在磁盘文件或资源中,并且只在需要时才加载。


组织模块。


考虑替换 Variant 数据类型。


使用动态数组,并在删除时回收内存。


回收被字符串或对象变量用过的空间。


消除死代码和无用的变量。
减少加载窗体数目
每一个加载的窗体,无论可视与否,都要占据一定数量的内存(其数量随窗体上控件的类型和数量,以及窗体上位图的大小等的不同而变化)。只在需要显示时才加载窗体,不再需要时,卸载窗体(而不是隐藏窗体)。记住,任何对窗体的属性、方法或控件的引用,或对用 New 声明的窗体变量的引用,都会导致 Visual Basic 加载该窗体。

当使用 Unload 方法卸载窗体时,只能释放部分窗体所占空间。要释放所有空间,可用关键字 Nothing 使窗体的引用无效:

Set Form = Nothing

减少控件数目
当设计应用程序时,窗体应尽量少用控件。实际的限制取决于控件的类型和系统,但实际上,含有大量控件的窗体将运行缓慢。一项与之相关的技术是:设计时,尽可能地使用控件数组,而不是在窗体上放置大量同类型的控件。

详细信息 关于控件数组的详细信息,请参阅“使用 Visual Basic 的标准控件”中的“使用控件数组”。

用标签代替文本框
标签控件占用的 Windows 资源比文本框少,因此,在可能的情况下,应使用标签代替文本框。例如,当窗体上需要一个隐藏的控件保存文本时,使用标签更有效。

保持数据在磁盘文件或资源中,并且只在需要时才加载
在设计时,直接放入应用程序的数据(象属性或代码中的文字字符串和数值)将增加运行时应用程序占用的内存。运行时从磁盘文件或资源中加载数据可减少占用内存。这对大位图和字符串特别有价值。

详细信息 关于向应用程序添加资源的详细信息,请参阅“再论编程”中“利用资源文件进行工作”。

组织模块
Visual Basic 只在需要时才加载模块—即当代码调用模块中的一个过程时,模块才被加载到内存。如果从未调用一特定模块中的过程,Visual Basic 决不加载该模块。因此,尽量把相关的过程放在同一模块中,让 Visual Basic 只在需要时才加载模块。

考虑替换 Variant 数据类型
Variant 数据类型使用极其灵活,但是比其它数据类型所占内存大。当要压缩应用程序多余的空间时,应考虑用其它数据类型替代 Variant 变量,特别是替代 Variant 变量数组。

每一个 Variant 占用 16 个字节,而 Integer 占 2 个字节,Double 占 8 个字节。变长字符串变量占用 4 个字节加上字符串中每一个字符占用 1 个字节,但是,每一个包含字符串的 Variant 都要占用 16 个字节加上字符串中每一个字符占用 1 个字节。因为它们太大,因此在用作局部变量或过程的参数时,Variant 变量是特别烦人的,这是因为它们消耗堆栈空间太快。

但在有些情况下,使用其它数据类型替代 Variant,灵活性降低了,为弥补损失的灵活性,不得不增加更多的代码。结果是大小没有真正的减小。

使用动态数组,并在删除时回收内存
使用动态数组代替固定数组。当不再需要动态数组的数据时,用 Erase 或 ReDim Preserve 放弃不需要的数据,并回收数组所用内存。例如,用以下代码可回收动态数组所用空间:

Erase MyArray

这里,Erase 完全删除数组,ReDim Preserve 则只缩短数组而不丢失其内容:

ReDim Preserve MyArray(10, smallernum)

删除了固定大小数组,也不能回收该数组所占空间—只是简单地清除数组每一元素中的值。如果元素是字符串,或包含字符串或数组的 Variant 变量,那么删除数组可回收这些字符串或 Variants 所占内存,而不是数组本身所占内存。

回收被字符串或对象变量用过的空间
当过程结束时,可自动回收(非静态)局部字符串和数组变量所用空间。但是,全局和模块级的字符串和数组变量一直存活到整个程序结束。要想应用程序尽量小,就得尽可能回收这些变量所用空间。将零长度字符串赋给字符串变量,可回收其空间:

SomeStringVar = "" '回收空间。

同样地,将对象变量设置成 Nothing 可回收该对象所用的部分(而不是全部)空间。例如,删除一个 Form 对象变量:

Global F As New StatusForm

F.Show 1 'Form 加载并以模态显示。
X = F.Text1.Text '用户按下按钮
'隐藏窗体。
Unload F '删除窗体可视部分。
Set F = Nothing '回收空间(模块数据)。

即使没有使用显式窗体变量,也应注意将不再用的窗体卸载,而不是简单地隐藏。

消除死代码和无用的变量
在开发和修改应用程序时,可能遗留了死代码— 代码中的一个完整过程,而它并没有被任何地方调用。也可能声明了一些不用的变量。虽然,在创建 .exe 文件中,Visual Basic 确实可删除无用的常数,但不能删除无用的变量和死代码。注意要复查代码,查找并删除无用的变量和死代码。例如,Debug.Print 语句,在运行 .exe 时被忽略,可它常常出现在 .exe 文件中。

当创建 .exe 文件时,含有字符串和变量作为参数的 Debug.Print 语句不会被编译。但是,对于含有函数作为参数的 Debug.Print 语句,其本身被编译器忽略,而函数则被编译。因此,在应用程序运行时,函数被调用,但返回值被忽略。因为,在 .exe 文件中,函数作为 Debug.Print 的参数出现时,将占用空间和 CPU 周期时间,所以在生成 .exe 文件前,最好删除这些语句。

在“编辑”菜单中使用“查找”命令搜索特定变量的引用。或者,当每个模块都含有 Option Explicit 语句时,通过删除或注释该变量的声明,并运行应用程序,可迅速发现变量是否被使用。若该变量被使用,则 Visual Basic 将出错。若不出错,则该变量没被使用。

详细信息 关于 Debug.Print 语句的详细信息,请参阅“调试代码和处理错误”中“在立即窗口中打印信息”一节。
-------------------------------------------------------------------------------
修剪图形


图形(图片和图形方法)要消耗许多内存。从某种程度上说,这是不可避免的:图形包含很多信息,所以规模巨大。但在许多情况下,通过以下方法,可减少图形对应用程序大小的影响:

使用 Image 控件显示位图。


需要时从文件中加载位图并共享图片。


使用 PaintPicture 方法。


释放图形所用内存。


使用 RLE 格式位图或元文件。
使用 Image 控件显示位图
在许多 Visual Basic 应用程序中, Picture 控件仅仅被用于单击和拖放。如果您也是这样使用 Picture 控件的,这就浪费了许多 Windows 资源。为了避免浪费资源, Image 控件就比 Picture 控件好。每一个 Picture 控件是一个真正的窗口,使用了大量的系统资源。而 Image 控件是轻图形控件而不是一个窗口,并且使用的资源不多。其实,典型情况是:使用五到十个 Image 控件相当于使用一个 Picture 控件。另外, Image 控件重画的速度比 Picture 控件快。只有在需要仅 Picture 控件才有的性能时才使用它,如动态数据交换 (DDE)、图形方法或包含其它控件的能力。

需要时从文件中加载位图并共享图片
在设计时,设置 Picture 属性,图形就会被添加到窗体中,增加了窗体在运行时所用的内存。通过将图片存储资源文件,并在运行时使用 LoadResPicture 加载图片,可以减少内存消耗。如果并没有用到所有与窗体关联的图片,那么这一技术比将所有图片存储在窗体上的控件中节省内存。而且,由于在窗体显示前,并不需要加载所有的图片,因此加快了窗体的加载速度。

此外,可在多个 Picture 控件、 Image 控件和窗体之间共享相同图片。如果使用下列代码,则只须维护一个图片副本:

Picture = LoadPicture("C:\Windows\Chess.bmp")
Image1.Picture = Picture '使用相同的图片。
Picture1.Picture = Picture '使用相同的图片。

与上面相比,下列代码加载了同一位图的三个副本,占用了更多的内存和时间:

Picture = LoadPicture("C:\Windows\Chess.bmp")
Image1.Picture = LoadPicture("C:\Windows\Chess.bmp")
Picture1.Picture = LoadPicture("C:\Windows\Chess.bmp")

同样地,如果在设计时将相同的图片加载到几个窗体或控件中,每一个窗体或控件都存储了该图片的一个副本。然而,应该将图片存于一个窗体中,而让其它窗体或控件用上述的方法共享。这将使应用程序既小(因为不包含冗余的图片拷贝)又快(因为不必从磁盘中多次加载)。

使用 PaintPicture 方法
不必总将位图直接放于控件上,也可以使用 PaintPicture 方法在窗体任何地方显示位图。当在窗体中重复平铺一个位图时,这种方法特别有用:只须加载位图一次,但可以使用 PaintPicture 绘制多次。

释放图形所用内存
当不再使用窗体、图片框或图形控件中 Picture 属性的图片时,将 Picture 属性设置成 Nothing,释放空间:

Set Picture1.Picture = Nothing

如果使用图片框或窗体的 Image 属性,Visual Basic 创建一个 AutoRedraw 位图(即使 AutoRedraw 属性是 False)。在 Image 属性用完后,将 AutoRedraw 设置成 False 之前,用 Cls 方法可回收该位图所占内存。例如,下列代码回收 mypic 控件中 Image 属性所用内存:

mypic.AutoRedraw = True '打开 AutoRedraw 位图
mypic.Cls '清除。
mypic.AutoRedraw = False '关闭位图。

使用 RLE 格式位图或元文件
Visual Basic 的缺省图片格式是 bitmap (.bmp),但也可使用其它图形文件格式。有几种绘图和图形程序允许将位图存为标准压缩位图格式,称作行程编码 (Run Length Encoded) (.rle)。RLE 位图比非压缩副本小几倍,特别是那些包含大片实心颜色的位图,而且它们在加载或显示时一点也不慢。使用元文件可节省更多的内存—有些情况下,可达 10 倍或者更多。当元文件被放大或缩小时,绘图速度很慢,所以最好以原图大小使用元文件。

从 Visual Basic 5.0 开始,也支持 .gif 和 .jpg 格式。这些格式一般比较小,但是,在选择格式时应权衡图形质量和加载速度。
--------------------------------------------------------------------------------
分段应用程序


Visual Basic 提供一种以新方法设计应用程序的体系结构。代替单一的整体执行程序,可以写一个这样的应用程序,它包含一个核心的前端执行程序,并由许多 ActiveX 部件来支持。这种方法有以下几个显著的优点:

部件在需要时加载,不再需要时卸载。


在 Windows 95 或 Windows NT 下,即使应用程序的其它部分是 16 位部件,跨进程的部件也可以是 32 位的执行程序。


远程部件可使用网络上其它机器的资源。
另外,部件可被单独调试并可在其它应用程序中重用。也许,这不能提高创建应用程序的速度,但可提高创建下一个应用程序的速度。

在确定如何使用分段技术最优化应用程序之前,必须估计到能创建的部件类型和怎样适合应用程序。使用 Visual Basic 专业版和企业版,能创建以下三类部件:

跨进程


进程内


远程
三种类型并不互相排斥:可以在一个应用程序中同时使用这三类部件。但从优化应用程序的观点看,它们各有极不相同的特性。

详细信息 在 Visual Basic 专业版和企业版所提供的《部件工具指南》中深入讨论部件的创建。

跨进程部件
跨进程部件是一个可执行程序,它可以向其它程序提供服务。象所有的可执行程序一样,启动后,在自己的进程空间内有自己的堆栈;因此,当作为客户使用由的应用程序使用部件提供的对象时,操作将从客户的进程空间转到部件的进程空间─ 因此而得名。与其它类型相比,跨进程部件提供了一些很有价值的特点:

异步操作(“线程”)。


非模态窗体。


部件中不能捕获的错误不会导致调用应用程序崩溃。


在 16 位和 32 位应用程序之间互操作。
当然,从优化观点看,第一点和最后一点最有意义。

因为跨进程部件是一个分离的程序,可以与作为客户的部件异步操作。它有一个单独的“线程”,与客户程序构成多任务(从技术上讲,这不是线程,而是一个分离的进程;但从概念上看,二者是等价的)。两个程序可相互通讯并共享对象,但它们是独立运行的。当应用程序需执行一些费时的操作时,异步操作特别有用。客户可先调用部件执行该项操作,而后继续响应用户。

即使应用程序将在 32 位系统上运行,如果信信惯用的 16 位应用程序或部件,可以不必立即将它们改成 32 位。若使用跨进程部件将应用程序分段时,则可将 16 位和 32 位部件混合在一起并相互适应。这将有助于充分利用 32 位特性,并保护了在 16 位部件上的投资。

考虑它们所有的能力,跨进程部件都有一个明显的缺点:性能。以下几点可显现这些不足:

启动速度


跨进程调用的开销
跨进程部件是一个由 Visual Basic 创建的执行程序,因此,与应用程序的启动相关的启动问题也同样存在。好在,当从另一个 Visual Basic 程序中调用在 Visual Basic 中写的跨进程部件时,几乎所有的支持 DLL 已经被加载。这就大大缩短了启动部件的时间。许多部件比 Visual Basic 应用程序的平均规模还小,它们具有很少或根本没有要加载的窗体,这又进一步缩短了加载时间。然而,跨进程部件启动总比进程内部件慢。

一旦运行起来,跨进程部件就必须承受它的固有缺点:部件间每一次互操作就是一次跨进程的调用。跨越进程边界占用大量的 CPU 周期。因此,从跨进程部件引用对象要比从客户应用程序自身引用或从进程内部件中引用付出更多的代价。减少代码中跨进程的调用,就可以减少跨进程调用开销的影响。

进程内部件
进程内部件在其进程空间内向其它程序提供服务。与跨进程部件相比,进程内部件有两个优点:

改善加载时间


无跨进程开销
对进程内部件来说,既无须创建新的进程,也不必加载运行时 DLL。因此,进程内部件比跨进程部件加载速度快得多。

因为它是在进程内的,在引用部件提供的对象的方法或属性时,就没有跨进程开销。因此,部件的对象操作起来与客户应用程序自身中的对象一样效率很高。

当然,对进程内部件也有一些限制。最重要的可能是:部件必须是 32 位,并且不能使用模态窗体。

远程部件
在 Visual Basic 企业版中,可创建远程部件,该部件能在网络任何地方的机器上单独运行。虽然,网络开销将不可避免地为应用程序性能付出代价,但可通过使用别的 CPU 资源来弥补。当使用远程部件,并且部件操作的数据对包含部件的机器来说是本地数据时,这样做尤为正确。这是因为数据必须从网络中其它地方获取,部件可在本地操作数据,之后只通过网络返回结果,这可能是比较有效的。

例如,可在部件中编写一个对象,用于搜索本地硬盘中满足特定条件的文件。将该部件做成远程部件,并在网络的所有机器上放置一个副本,再编写一个分布式文件查找程序,就可使用所有这些 CPU 资源并行搜索所有网上部件。

详细信息 在 Visual Basic 企业版所提供的《客户/服务器应用程序开发指南》中深入讨论了远程部件。
LiaoCheng 2001-11-07
  • 打赏
  • 举报
回复
哇,老兄也有这种情况,同喜同喜!!
但是怎么解决这种问题呢,我的客户的机器配置并不好,只有64M内存,单单运行我的程序都有点停chi现象,真不好办啦!!!
WxmJun 2001-11-07
  • 打赏
  • 举报
回复
你已算幸运了,俺一下子就用了36m
我根本没用过activex ocx
Bardo 2001-11-07
  • 打赏
  • 举报
回复
不用activex ocx

7,759

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧