How to Optimize Memory Management in VB 3.0 for Windows
ID: Q112860
|
The information in this article applies to:
-
Microsoft Visual Basic Standard and Professional Editions for Windows, version 3.0
SUMMARY
This article outlines how various memory areas in Visual Basic are managed.
It covers the following areas:
- General Memory Management:
- Windows Limits
- Application Limits
- Form Limits
- Data Limits
- Global Name Table
- Global Symbol Table
- Global Data Segment
- Module Name Table
- Module Symbol Table
- Module Data Segment
- Module Code Segment
- System Resources
- Stack Space
- When Code and Resources are Loaded and Unloaded
- "Out of Memory" and Related Error Messages:
- Common Ways to Avoid "Out of Memory"
- Common Ways to Diagnose "Out of Memory"
- Verifying a Memory Leak
- Optimization Recommendations
- System Resource Overview
- Visual Basic Controls: USER Resource Byte Use
- Menu USER Resources
- System Resource Optimizations
- Size Optimizations
- Speed Optimizations
GENERAL MEMORY MANAGEMENT
Windows Limits
Windows version 3.1 imposes a limit of 600 windows in existence at one
time. All windows in all applications running in Windows count toward this
limit. In Visual Basic, each form and non-graphical control (all controls
except shape, line, image, and label) counts as one window.
Application Limits
- There can be a maximum of 256 distinct objects in a project.
- There can be a maximum of approximately 230 forms in a project, with up
to 80 loaded at one time.
- The total count of all procedures, form and code modules, and DLL
declarations must be less than 5,200, not counting event procedures
that are empty of code.
Form Limits
- There can be a maximum of 470 controls on a single form, depending on
control type.
- There can be a maximum of 254 different control names per form. A
control array counts as one name.
- The data in all form properties and all control properties on a given
form is stored in a single data segment limited to 64K, except for the
List property of combo and list-box controls and the Text property of
multiline text-box controls.
Data Limits
Specific data limits for Visual Basic version 3.0 are well documented in
Appendix D of the Microsoft Visual Basic "Programmer's Guide." Please look
there for information on data limits.
Global Name Table
Each application uses a single Global name table (up to 64K in size)
that contains all Global names. Global names include the following:
- The actual text of the Form or Code module name.
- The actual text of each event procedure name appears in the Global
symbol table only once. For example, two different forms each have a
Form_Load event procedure, but only one entry for the event procedure is
made in the Global symbol table.
- The actual text of each non-event Sub or Function procedure name in a
form module (.FRM file). Even though these Sub or Function procedures
are private to the form, within the application, their names are listed
globally but with a flag set to indicate that they are private to that
form.
- The actual text of each non-event Sub or Function procedure name in a
code module (.BAS file). As with Sub or Function procedure names in a
form module, the code module Sub and Function procedure names are listed
globally but with a flag set to indicate that they are global to the
application (unless the Private key word is used, in which case the
flag is set to indicate that they are private to that code module).
- The actual text for the name of each Global constant.
- The actual text for the name of each Global variable.
- The actual text for the name of each user-defined type definition.
- The actual text for the name of each Global DLL Sub or Function
procedure declaration.
- Four bytes of overhead for each of the above listed Global names in the
Global name table as well as approximately 100 bytes of overhead for the
hash table for these Global names.
NOTE: When your project is made into an .EXE file, most of the Global name
table is not needed. Visual Basic takes special provisions to ensure that
only the names that are needed are included with the .EXE (such as DLL
function names).
Global Symbol Table
Each application has a single Global symbol table that is up to 64K in
size. This table contains descriptive information about each of the items
named in the Global name table. Specifically, this table contains:
- Type definitions: 4 bytes for the type plus 4 bytes for each element.
- Type variables: 12 bytes.
- Fixed-string variables: 12 bytes.
- Object variables: 12 bytes (approximately).
- Everything else: 10 bytes (approximately).
- Approximately 100 bytes of overhead for the hash table within the Global
symbol table.
NOTE: When your project is made into an .EXE file, the Global symbol table
does not exist. It is only needed within the Visual Basic environment to
create the .EXE file itself.
Global Data Segment
Each Visual Basic application receives a single data segment of up to 64K
(minus overhead) to store the actual data referenced by Global variables
and Global constants.
Space for Global string constant descriptors is also allocated in this data
segment. However, the actual string data for the Global string constant is
stored in a segment of up to 32K (minus overhead) allocated separately from
dynamic memory.
A custom control (.VBX) is allocated space in the same 32K segment for any
strings obtained with the Visual Basic API VBCreateHlstr. If the custom
control does not deallocate this space, because it needs to reference
these strings when it is unloaded or it doesn't clean up properly, the data
in the segment may exceed 32K. If this occurs, Visual Basic allocates
another segment to hold the excess data and links this new segment into the
dynamic data segment chain.
Module Name Table
Each form and code module has a single Module name table that is up to 64K
in size. The Module name table includes:
- The actual text for the name of each module-level and local variable
name.
- The actual text for the name of each module-level DLL Sub or Function
procedure declaration.
- The actual text used for line numbers and line labels.
- As with the Global name table, an additional four-byte overhead for each
of the above listed module-level names in the Module name table as well
as about 100 bytes overhead for the hash table for these module-level
names.
NOTE: As with the Global name table, when your project is made into an .EXE
file, most of the Module name table is not needed.
Module Symbol Table
Each form and code module has a single Module symbol table that is up to
64K in size. The module symbol table contains much of the same information
as the Global symbol table, except for Type definitions.
NOTE: As with the Module symbol table, when your project is made into an
.EXE files most of the Module name table is not needed.
Module Data Segment
Each form and code module has its own 64K module data segment. The
contents of the module data segment include:
- Local variables declared with the Static keyword.
- Local variables declared within a Static Sub or Function procedure.
- Module-level, fixed-length string variables.
- Module-level variables other than arrays and variable-length strings.
- Module-level constants.
- Tracking data for arrays and variable-length strings (2-byte pointer
each).
- Tracking data for controls referenced in code for a form (2-byte
pointer each).
- Tracking data for nonstatic local variables (2-byte pointer each).
Module Code Segment
Each Sub or Function procedure in a form or code module can contain up to
64K of p-code (the internal representation of your code). The module-level
declaration section of each form or code module can also contain up to 64K
of p-code. If the procedure-level or module-level p-code exceeds this
limit, Visual Basic generates an "Out of Memory" error message. There is no
specific internal limit to the total size of an individual form or code
module.
The amount of p-code in a procedure or in the Declarations section of a
module is roughly equivalent to the number of ASCII text characters in the
code. The Visual Basic documentation recommends that you save your forms
and modules as ASCII text and that you keep the size of individual
procedure-level or module-level code in your form and code modules to under
64K. However, practical experience by Visual Basic programmers has shown
that it is best to keep the size of these under 45K to 50K of ASCII text.
This estimate is true only when you are in the development environment.
Visual Basic does not include identifiers (procedure, variable, and object
names) or comments in the .EXE files you create, so the resulting .EXE is
much smaller. If you don't exceed the 64K limit on p-code in the
development environment, you won't exceed it in the finished .EXE.
System Resources
The data space (heap) attached to the Windows libraries (USER.EXE and
GDI.EXE) is the space allocated for system resources. The data space used
by the GDI library contains graphics information regarding brushes, fonts,
icons, and so on. The data space used by the USER library contains style
information pertaining to windows (forms) and controls. The data space for
each of these libraries is limited to 64K. The "About Program Manager" menu
command displays, as a percentage, the lower of these two areas of memory.
If you run out of either of these two heaps you will receive an "Out of
Memory" error message.
Visual Basic uses Windows resources shared with other Windows applications,
so it is important to make efficient use of these resources to avoid "Out
of Memory" messages. For larger applications, you should reduce the number
of forms and controls loaded at any one time. Forms should be loaded only
when needed. Here are some ways to reduce the number of controls:
- Use the Visual Basic Load and Unload statements to load forms only when
needed at run time.
- Use so called lightweight controls (labels, images, lines, and shapes
in Visual Basic version 3.0) when possible. These controls are similar
to other controls in that they do use system resources when they are
being drawn or updated in the screen. But unlike other controls, the
lightweight controls release resources back to the system when
finished.
- Replace controls such as command buttons that react to mouse events
with an image control that has a picture of a control in it. This
provides your application with similar functionality but uses less
memory (system resources).
- Try to replace several related controls with a single, larger control.
For example, if several text boxes were placed on a form to represent
the cells of a spreadsheet, you could replace these controls with a
single picture control containing an image of the cells: lines drawn
vertically and horizontally. Hit testing could be performed at run time
from within the MouseDown event of the picture control. In other words,
you could use the x and y coordinates passed to the MouseDown event to
determine which "cell" was clicked (hit). The cell image on the picture
control could be temporarily replaced by a real text box, positioned
by using the Move method to allow for user input. In this manner,
only two controls would be required to simulate input on a spreadsheet:
a picture control and a text box.
Stack Space
Each Visual Basic application uses a single stack limited to 20K in size.
The 20K size cannot be changed, so an "Out of Stack Space" error can easily
occur if your program performs uncontrolled recursion, such as a cascading
event.
Visual Basic itself uses the stack, even in a .EXE, so the practical limit
is lower than 20K. A simple way to get an idea of this to make an .EXE
file of a form with a single command button on it with the following code.
Each Gosub takes 4 bytes of stack space, so you can then calculate how much
free stack space you had when your procedure started.
Sub Command1_Click ()
Dim frameCount as Integer
frameCount = 0
Overflow_Stack:
Me.Cls
frameCount = frameCount + 1
Print frameCount * 4
GoSub Overflow_Stack
End Sub
Procedure arguments and local variables in Sub and Function procedures take
up stack space at run time. However, Global variables, module-level
variables, and procedure-level variables declared with the STATIC keyword,
and arguments in Sub or Function procedures that are defined with the
STATIC keyword, don't take up stack space because they are allocated in the
Module Data Segments of form and code modules.
When Code and Resources Are Loaded or Unloaded
When an application is executed, memory is allocated for the Global Data
Segment and the appropriate data is loaded into it. This stays persistent
until the application terminates.
When a form is loaded, system resources are allocated for the Form and all
controls on that form. In addition, memory is allocated for the Module data
segment and the appropriate data is loaded into it.
Each Visual Basic form or module consists of one or more code segments in
the .EXE file. The code segments are marked LOADONCALL, MOVEABLE, and
DISCARDABLE, which you can verify by using a copy of EXEHDR.EXE to dump the
file header information. Thus, on first reference to the form or module,
Windows loads the code associated with it. Windows is then free to discard
it and demand-load it as it sees fit (for example, if you run low on
memory). Unloading a form will not force the code segment out of memory,
it's still present until Windows decides to discard the code segment.
Unloading a form does unload the instance of that form and all resources
used by it and the controls on that form. However, when a form is unloaded,
the Module Data Segment is not unloaded; it remains in memory until the
application terminates. Thus, if you load a Form, change the values of some
module level variables, unload the Form, and then load it again, the value
you last assigned to the module level variable in the Form will still be
present. To deallocate memory used by the Module data segment in the form,
use the following line of code after you unload the form:
Unload Form2
Set Form2 = Nothing
This will clear all data in the Module code segment for the form.
"OUT OF MEMORY" AND RELATED ERROR MESSAGES
Common Ways to Avoid "Out of Memory"
Here are some tips to help you avoid the "Out of Memory" error message:
- Read Appendix D (Specifications and Limits) of the "Programmers Guide."
The discussion of the Global symbol table in the manual is enhanced
by details presented below.
- Read Chapter 11, "Optimizing Your Applications for Size and Speed," in
the "Programmer's Guide." This offers a good starting place in its
discussion of optimizing your applications memory requirements.
- Keep the number of forms loaded at any given time to as few as possible.
While the specifications indicate that 80 forms can be loaded into
memory, in practice you will want to avoid pushing this upper limit.
- If possible, take advantage of non-graphical ("lightweight") controls
(shape, line, image, and label). These controls use less system
resources as well as memory.
- Use control arrays if possible rather than a large number of static
controls of the same type.
- Minimize the number of controls on a form. The upper limit of
controls on a form is 470; however, they can use only 254 control
names (making control arrays necessary). In practice, a form this
heavily laden with controls would be slow in performance. Minimize the
number and type of custom controls on a given form.
- Save your forms and modules as text. See the "Module Code Segment"
discussion above for details.
- Ensure that the declaration for any API or other DLL calls you make
are correct. Ensure that memory allocated by routines inside a DLL is
actually deallocated when the process using it is finished.
- Explicitly turn off timer controls when your application exits. If
you do not, it is possible the parent form will not be unloaded, and
the timer will continue firing.
- Explicitly unload forms; especially when the application terminates.
The End statement does not trigger the Unload event of a form. The
only way to ensure that a form is actually unloaded is to issue the
Unload statement. The Forms Collection is useful for being certain
that all forms, loaded or not, are unloaded.
There is a special version of error #7, "Out of Memory -- Global Name
Space", which can occur when the name space is filled. To deal with this
error, minimize the size of the names used in event, private, and Global
Sub and Function procedures. See the "Global Name Table" discussion above
for details.
Common Ways to Diagnose "Out of Memory"
When you receive an "Out of Memory" error, there may be few limits to the
lengths you will have to go to diagnose and locate the actual source of the
problem. Make a backup of your project and place it in a temporary
directory. Take any drastic measures on that backup copy. The following are
some tips to help you narrow the focus in finding the cause of the "Out of
Memory" error:
- Remove any and all unnecessary device drivers from the CONFIG.SYS file.
Is there any particular problem that seems to induce the error?
- Remove any TSR (terminate and stay resident) programs from the
AUTOEXEC.BAT file. Again, is there any particular TSR that induces the
error?
- Use Program Manager as the Windows desktop.
- Do not run anything else in Windows that is not necessary. Check
this by bringing up the task list (CTRL-ESC). Are Visual Basic and
the Program Manager the only tasks running?
- Change the Windows Video driver to standard VGA. It may be necessary
to check if your display's vendor has released an update to the
display driver. There may an incompatibility with your video driver
and Visual Basic causing video memory to be incorrectly allocated or
referenced.
- Change any API or DLL calls you are making into comments by adding a
single quotation mark as the first character on the line. This may not
be conclusive, as the error can be generated as a result of the values
returned by the calls, and not the calls themselves. In that case,
hard code the return values, or provide some mechanism to simulate
their action so you can test the code that responds to them.
- Remove any custom controls you are using from the form.
- Check to see whether you are legitimately low on RAM or the hard disk
is almost full. 386 enhanced mode gives you more logical RAM than you
have physical RAM, but only if you have the hard disk space free to
allow this.
Verifying a Memory Leak
Memory leaks can occur when memory is allocated to perform a particular
process but is not deallocated when the process concludes.
You can use a tool such as HeapWalker from the Windows Software Development
kit or Visual C/C++. HeapWalker allows you to analyze your application's
memory requirements and memory profile by seeing how many code segments
from your application are in memory at any given time. WPS.EXE which ships
with the Visual Basic CDK in the professional edition, can be used to
determine which .DLL and .EXE files are running.
The Windows API GetFreeSpace() function scans the Global heap and returns
the number of bytes of memory currently available. However, the results of
function in a large application can be misleading. The best way to use this
function is to create a demonstration program that tracks memory before and
after a given process. It is important to minimize the scope of that
process as much as possible or else the results will be inconclusive.
OPTIMIZATION RECOMMENDATIONS
Optimization techniques are generally a trade-off between size and speed.
Some optimizations have multiple effects, for example, reducing size can
improve speed because less memory may be needed which causes less disk
swapping. Some Visual Basic speed optimizations affect system resource
availability.
System Resource Overview
Under Windows 3.x system resources fall into one of two categories, USER
and GDI. USER resources consist of Window and Menu handles. GDI resources
consist of Device Context handles, Brushes, Pens, Regions, Fonts, and
Bitmaps. USER and GDI resources are stored in the corresponding Windows
internal DLL's data segments which have a maximum size of 64K. Resource
availability refers to how much of the 64K data segment is still available
for new resources. A resource handle is an offset into the data segment to
the resource's internal control structure.
The Program Manager's available resource indicator in the About Box
displays the least available of the two type of resources. The biggest
violator of USER resources is the creation of windows (for example, Dialog
Boxes, Forms, Controls). Every window has a variable length internal
control structure. The base size for a Window's control structure is 64
bytes. Additional bytes are specified by the Window's Class in order to
support the specific functionality of the window. Standard controls in
Windows and Visual Basic consume from 66 to 160 bytes. Visual Basic
includes 4 graphical controls (Label, Shape, Line, and Image) which do not
create Windows and hence consume ZERO USER resources.
Visual Basic Controls: USER Resource Byte Use
Form .......... 206 | FileListBox .... 160 | PictureClip ..... 72
MDIForm ....... 420 | Shape ............ 0 | SpinButton ...... 72
PictureBox ..... 90 | Line ............. 0 | SSCheck ......... 72
Label ........... 0 | Image ............ 0 | SSFrame ......... 80
TextBox ........ 76 | Data ............ 72 | SSOption ........ 72
Frame .......... 74 | Grid ............ 72 | SSCommand ....... 76
CommandButton .. 66 | OLE ............ 164 | SSPanel ......... 80
CheckBox ....... 76 | AniPushButton .. 170 | SSRibbon ........ 80
OptionButton ... 76 | CommonDialog ... 166 |
ComboBox ...... 136 | CrystalReport .. 166 |
ListBox ....... 160 | Gauge ........... 80 |
HScrollBar ..... 80 | Graph ........... 80 |
VScrollBar ..... 80 | MhState ......... 72 |
Timer .......... 72 | MSComm .......... 72 |
DriveListBox .. 160 | MaskEdBox ....... 76 |
DirListBox .... 160 | Outline ......... 82
Menu USER Resources
Menus also consume USER resources although their impact is very minimal.
An application could have a total of several hundred menu options and still
only increase the USER resource use by 24 bytes. There is ZERO resource
use for the top level menu. USER resources are consumed and freed
dynamically as menus are opened. The first level drop-down menu consumes 24
bytes. The second, third, forth, and so on consume 132 bytes each of USER
resources. For example, a displayed third level menu would consume 288
bytes, 24 bytes for the first level, 132 bytes for the second level, and
132 bytes for the third level. Popup menus that can appear anywhere on the
screen, usually at the mouse cursor location, also consume 132 bytes of
USER resources.
System Resource Optimizations
The best way to reduce USER resources is to reduce the number of created
windows at any one time. Any loaded form consumes USER resources regardless
of whether it is visible:
- Break large forms (forms with many controls) into several smaller forms.
Each of the smaller forms can be loaded and unloaded as necessary. Since
only one of these forms at any given time is loaded, system resources
will be used less. However, the added overhead of loading and unloading
forms will most likely result in slower application performance, so
there is a tradeoff.
- Implement control simulation. For example, a form could implement a
toolbar by using 20 command buttons, consuming 1320 bytes of system
resources. The toolbar can be implemented more efficiently with two
image controls and one PictureClip control. The first image control
contains one bitmap that looks like the entire toolbar. The PictureClip
control contains one bitmap that contains the button down appearance of
all buttons on the toolbar. When the user clicks on the toolbar (image
control) the corresponding down picture is retrieved from the
PictureClip control, placed in the second image control, and placed over
the toolbar in the correct position. The second image control is hidden
on the mouse up giving the appearance of button depression. This
solution consumes 72 bytes of USER resources for the one PictureClip
control. The image controls are graphical controls which consume zero
USER resources.
A second area of control simulation is text boxes. Applications that are
data entry intensive contain many text-box controls. For example, if a
form contained 64 text-box controls, they would consume 4864 bytes of
USER resources. A simulation solution would use 1 text-box control and
64 label controls. When the user clicks on a label to edit it, the text
box is resized and moved to the clicked label. This requires more coding
to handle the one text box, tabbing, and access keys. This solution
consumes 76 bytes of USER resources for the one text-box control. The
label controls are graphical controls which consume zero USER resources.
- Consider redesigning the user interface. For example, many option
buttons can be replaced by one combo box and many check boxes can be
replaced with one multiselect list box. Some controls may be an overkill
for the desired functionality. For example, using a picture box, when
all that is needed is an image control.
Size Optimizations
The following are recommendations intended to help produce the smallest,
fastest code possible. Please note that although saving two bytes here or
four bytes there may not seem like a lot, just implementing recommendation
3 for null-length strings ("") globally throughout a product can provide
significant size reduction! Furthermore, Visual Basic uses a scheme of
aligning segments on a 256-byte boundary in the EXE, which means that if
you use just one byte beyond the current 256-byte block, another 256-byte
block will be allocated! So, some of these optimizations not only result
in a time savings, they can also result in much smaller code!
- Put strings into external DLL's:
- Doing this gives a much greater ease of converting text into
other languages.
- It also helps reduce the sizes of the code segments in the Visual
Basic app.
- It slightly slows down the initial loading of forms.
- Strings can be stored in a String Table Resource inside the DLL.
- Reduce unnecessary code replication.
Having the same code in multiple places will generally increase the size
of the app. It also increases maintenance costs. In some cases it may be
necessary to have the same code in multiple places, and such instances
should be commented to indicate the need.
- Use Constants rather than string literals:
- When used as a parameter, a string literal takes up a minimum of
6 bytes, whereas a string *constant* takes 4 bytes.
- When assigned to a string variable, a string literal takes up a
minimum of 8 bytes versus the 4 bytes for a string constant.
- Converting a parameter from a string literal to a string constant
saves 4 bytes in the code segment, for every instance beyond the
first.
- Converting an assigned string literal to a string constant saves 2
bytes in the first instance, and 6 bytes for every instance beyond
the first.
- For strings that are used throughout the program and are Read Only, use
Global string variables. Be cautious about this approach since the
Global Symbol Table has a limit of 64k for storing variable names. It[ASCII 146]s
best to use this method for strings that are repeated a lot.
Define the strings as Global, set them up in an Initialization module,
and then use them in other modules instead of constantly recreating
things like Chr$(9):
Global TABCHR as String * 1
Global CR as String * 1
Global CRLF as String * 2
Sub Init()
TABCHR = Chr$(9)
CR = Chr$(13)
CRLF = CR + Chr$(10)
End Sub
By constantly using Chr$(9), the code is larger, and it is slower since
it must re-create the character every time that code is executed.
- Put IF/THEN constructs on one line if possible.
The ENDIF generally takes up 6 bytes, thus changing:
If X=2 Then
debug.print "HI"
EndIf
to:
If X=2 Then debug.print "HI"
This winds up saving 6 bytes to do the exact same function.
- Check to see whether the Visual Basic function you're using is really
needed.
Sometimes this means checking the function to see if the returned value
really needs the additional work you're doing, such as:
Trim$(Format$(123))
In which case, the Trim$() is totally unnecessary. Other times, this
means looking at what is being created, and seeing if it could be done
at design time, such as " 0" instead of using Str$(0).
- Put functions that are only used one time, or are used seldom in their
own modules. Visual Basic loads modules on demand and Windows will
discard them if they don[ASCII 146]t get used after a while:
- Modules such as a Print module and an Initialization module can be
loaded one time by the code and then discarded when no longer
needed.
-or-
- If a special startup form is going to be used, the
initialization code could be placed in that form, so the code will
be unloaded with the form.
- Use Bit fields rather than strings.
Not only does an integer take up less space in memory than a 16
character string, but it is much faster to do comparisons! i.e., it
would be much faster, and more efficient, to check for the existence of
multiple flags via:
If (Flags And TestVal) Then ...
than an associated routine which has to scan multiple characters in a
string to see if any of them are a "0" or "1".
- Remove unnecessary value checks.
For example:
If bFlagToBeTested = True Then ...
can be written as:
If bFlagToBeTested Then ...
Removing the "= True" saves 6 bytes from the module or form and is
faster to execute. (Note: It also means that any non-zero value can be
evaluated as "True".)
- Do calculations manually at design time rather than asking the compiler
to do them at run time.
- If a data structure is only used for its size, store the size
information in a Global constant or variable rather than keeping the
entire structure around just to use the Len function. For example,
use Const COMPANYREC_LEN = 505, rather than using Len(COVar). This
avoids keeping a form-level variable around just so its length can
be calculated!
Or if the record sizes are being changed a great deal, then at least
move the calculation to an initialization module, and do it only one
time! In this case, a 505-byte data structure was loaded into
memory every time a form that used Company data was loaded.
- Even numeric calculations take up both execution time and space in
the EXE: For example, use MinFree& = 102400& instead of MinFree& =
1024& * 100&.
- Move graphics from the application to a DLL.
This reduces the size of the executable file for updates. The .EXE can be
updated and distributed without the redistribution of the graphics in the
DLL, assuming that the graphics have not changed.
Speed Optimizations
WARNING: The following methods are designed to help machines with low
memory (RAM). However, these methods may make debugging harder, and make it
harder to maintain and reuse code. Therefore, this tradeoff should be
considered when using the following techniques.
- Never reference an object property more than once.
Poor:
if Form1.Caption = "ABCD" then
elseif Form1.Caption = "DEFG" then
elseif Form1.Caption = "XYZ" then
endif
Better:
Temp$ = Form1.Caption
if Temp$ = "ABCD" then
elseif Temp$ = "DEFG" then
elseif Temp$ = "XYZ" then
endif
Even Better:
Select Case Form1.Caption
Case "ABCD"
Case "DEFG"
Case "XYZ
End Select
Best:
CONST CASE1 = "ABCD"
CONST CASE2 = "DEFG"
CONST CASE3 = "XYZ"
...
Select Case Form1.Caption
Case CASE1
Case CASE2
Case CASE3
End Select
The last version is the best, because it uses constants for the strings
(easier to maintain, less memory used, faster execution) and because it
only references the variable (Form1.Caption) one time, rather than
multiple times as the IF/ELSEIF constructs do. Using Select/Case
statements will result in faster execution, however, it will be at the
cost of slightly larger code.
- Avoid calling routines outside of the current form or module to reduce
swapping problems on low-memory machines
Calling routines in a central location is okay but this can lead to
inefficiency. A routine in one module which calls a routine in a second
module, which calls a third routine in yet another module, etc. means
that all of those modules have to be loaded. Doing this can cause
excessive hits on the Windows SwapFile. To alleviate this, make sure
that as many of the subordinate routines that your routine needs are
located in the same module.
- It is more efficient in Visual Basic to have local references to the
current form's controls than it is to reference the proper form and then
the control. Put subroutines or code that use controls in the form
instead of a module whenever possible. For example:
Module1
Sub DoWork
Form1.Text1.Text = "ABC"
End Sub
-versus-
Form1
Sub DoWork
Text1 = ABC
End Sub
- Make smaller modules:
Normal Windows programmers look for segment sizes in the range of 4-8k.
Since there is no easy way to determine how much space a particular
module in Visual Basic is taking up, sometimes we can only guess. The
best approach is to put subroutines that work together into the same
module. Then try to make that module as small as possible.
- Use specific object types:
- Use Windows API functions to draw artwork or backgrounds on the form
rather than using Picture boxes or Image controls. Using the Windows API
will help make some of the forms draw quicker.
REFERENCES- Visual Basic version 3.0 for Windows "Programmer's Guide," Appendix D,
"Specifications and Limitations," pages 641-646.
- Visual Basic version 3.0 for Windows "Programmer's Guide," Chapter 11,
"Optimizing your Application for Size and Speed," pages 255-263.
- Microsoft Windows Software Development Kit "Programmer's Reference,"
Volume 2, "Functions."
Additional query words:
3.00 MemLeak
Keywords : kbcode PrgOptMemMgt
Version : 3.00
Platform : WINDOWS
Issue type :
|