[AccessD] Early and Late-Binding Redux

Jim Lawrence (AccessD) accessd at shaw.ca
Wed Jul 28 13:15:19 CDT 2004


Hi Ken:

Great research.

Jim

-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com]On Behalf Of Ken Ismert
Sent: Wednesday, July 28, 2004 9:00 AM
To: 'Access Developers discussion and problem solving'
Subject: [AccessD] Early and Late-Binding Redux



After reading with interest the thread "More on early versus late binding",
the questions posed by the various responders prompted me to do some
research. This rather long post is the result. I have divided this post into
two main sections: Binding Performance, and an Under-The-Hood Look at VB/COM
Binding.

-Ken

BINDING PERFORMANCE
===================

Summary: Early binding is much faster than late, and is fastest under the
most typical Access usage situations. A compelling benefit of early binding
is the efficiency gained when coding. When testing object binding
performance, don't use objects which are bound to queries.

PERFORMANCE COMPARISON
What is the real-world performance difference between late and
early-binding? One test is measuring the maximum calls per second that can
be sustained using each method. The hands-down winner: early-binding. It is
roughly forty times faster for in-process calls, and about four times faster
for out-of-process calls (1). For typical Access programs, the majority of
objects are run in-process, especially Forms, DAO and ADO. Out-of-process
objects are most often used in Access when automating external programs like
Word or Excel.
  Another common scenario involves creating an object, calling it a few
times, and closing it. If we create and destroy objects frequently, we need
to look at object activation performance. Are late-bound objects more
expensive to create than early-bound ones? For in-process activation, its a
tie: both binding methods create objects in the same amount of time. For
out-of-process activation, it turns out that late-binding is more efficient
if you are making less than 10 calls to the object. But if you are going to
make more than 10 calls, early-binding has the edge (2).

PRACTICAL RULES OF THUMB
So, early-binding almost always beats late-binding in terms of performance,
but what does that mean to you? It depends on the level of object use in
your code. As a rule, the more complex your program, and the more it relies
on internal object interaction, the more it can benefit from early-binding.
However, if you are automating an external program, particularly across
different versions, late-binding is a viable option. As a professional, you
have to take binding and performance considerations into account if you are
going to deliver consistent value to your customers.
  The most critical performance consideration is, in my view, the human
performance of quickly and accurately coding an application. Look at what
you get with early-binding: Intellisense, compile-time checking, and events.
The first two are invaluable for catching errors before they reach
production, and the last is indispensable for writing efficient, clean code.
It helps you write solid code faster, which is a compelling reason to use
early-binding wherever it is warranted.

USING QUERY PERFORMANCE TO JUDGE OBJECT BINDING EFFICIENCY CAN BE MISLEADING
Recordset objects are poor candidates to judge object binding and activation
efficiency. When the underlying query is loaded, it must establish a
connection to the backend database (if the query involves linked tables),
parse the SQL and compile the query. These initialization costs, even in the
best cases, dwarf any object activation cost incurred. A much more
representative test would be to time repetitive opening, use and closing of
custom VB classes not tied to data objects.

AN UNDER-THE-HOOD LOOK AT VB/COM BINDING
========================================

Summary: Understanding objects in Access really means understanding COM,
because it is the object foundation for VB. In COM, all object binding is
done to interfaces. The object declaration determines whether a specific
(early-bound) or generic (late-bound) interface is used. The overhead of
late-bound object calls explains the performance disadvantages of this
technique. Early-bound calls use a much more efficient mechanism. References
are primarily used when coding and compiling early-bound references, not at
runtime. The details of object activation reveal more about the role of the
Registry, and how objects behave at runtime.

INTERFACE BINDING
In VB, object references bind to interfaces. An interface defines how
clients communicate with an object. It is composed of a fixed set of method
signatures. Think of it as the property and method declarations, with no
code, that a class supports. All VB classes have a default interface, which
is simply the public properties and methods in the class. VB classes can
also support one or more custom interfaces, which is an external interface
that a class agrees to implement.
  When declaring an object reference, you can specify that VB bind the
reference to a specific interface (default or custom), or no interface at
all, in which case VB supplies a generic interface for you, and binds to it.

LATE-BOUND REFERENCES
Late-bound references are determined solely by how the object reference is
declared (2):
    Dim obj As Object
    Dim obj As Variant
    Dim obj  ' Variant implied
No specific interface is declared, so the references are late-bound. In
late-binding, the object's default interface is hidden from VB, and can only
be accessed indirectly.
  To backtrack a little, all VB classes implement an interface called
IDispatch, originally developed to support automation. Hidden from the VB
programmer's view, IDispatch  provides a generic, runtime way of executing
properties and methods of the classes' default interface.
  All late-bound VB object references use the IDispatch interface. To
execute a method:
  1. VB first calls IDispatch.GetIDsOfNames with the method's name.
GetIDsOfNames looks up the name in the object's default interface, and
returns the dispatch ID, or DispID, of the method.
  2. Next, IDispatch.Invoke is called with the method's DispID and the
parameter list.
  3. If the method name is found, and the parameter list matches up, the
method is executed, and all is well. Otherwise, a runtime error occurs.
  In late-binding, this process is repeated every time the method is used.
This overhead accounts for a significant fraction of overall call time, and
explains a lot about the performance hit taken by late-binding. It is also
worth noting that for scripting environments like IE or ASP, late-binding is
the only binding technique available (2).

EARLY-BOUND REFERENCES
Early-bound references are again determined solely by the object
declaration:
    Dim obj As Library.CClass   ' Default interface
    Dim obj As Library.IInterface   ' Custom interface
Because an explicit interface is declared, these references are early-bound.
This allows VB to use vTable binding, the fastest, most efficient form of
binding. All VB objects, and most COM components, support vTable binding
(another form of early binding, called DISPID binding, is also supported,
but not discussed here).
  A vTable, or virtual function table, is a list of pointers to the methods
the interface supports. It is loaded into memory when the object is first
instantiated. To invoke a method, VB passes a pre-compiled offset to the
object's vTable, which is then resolved to the actual address of the method.
The overhead of a vTable-based call is little more than that of a DLL
function call, and is a fraction of the time required for a late-bound call.
  Additionally, a vTable can be shared by multiple instances of the same
object, which saves memory when dealing with collections of objects.

BINDING EXCEPTIONS
There are reference types in Access that exhibit both late and early-bound
qualities:
    Dim ctl As Access.Control
    Dim frm As Access.Form
These special case objects are inheritance objects. All controls inherit
Control, and all forms inherit Form. Notice that Intellisense works for the
common properties and methods for each type. But, you can also refer to
properties and methods that are not members of Form, and it will compile
without error. This lets you refer to specific controls on specific forms
using a generic Form reference. So, Form and Control appear to be both early
and late bound: default properties and methods are early-bound, while
references to specific form or control properties are late-bound. This
leveraging of inheritance allows great convenience in dealing with forms and
controls.

HOW VB USES PROJECT REFERENCES
Project References provide essential support for object-oriented
programming, but their role in the VB environment not well documented.
References are used when coding, compiling, and making install packages.
They do not play a direct role during runtime.
  You can make a Project Reference in one of three ways: selecting Tools,
References in the VB editor, selecting Insert, Components in VB editor, and
selecting Insert, ActiveX Control in Form Design.
  References provide needed object information for a VB project. The first
is the Class ID, or CLSID -- a unique GUID identifier for the class (11).
This is one of the registry keys that facilitates retrieval of an object's
type library, its server file (DLL, EXE, OCX), and other information. The
second is the Type Library, which holds the definition of the interfaces
supported by the object (1). Type Libraries drive IntelliSense and provide
the necessary information to compile code using early bound object
references.
  While coding, the aforementioned IntelliSense is the chief benefit of
References. These same type libraries can also be viewed using the often
underutilized Object Browser -- hitting F2 allows you to browse the type
libraries for each Reference you have made. Note that there is also a type
library for your VBA project, as well.
  During compilation, References are used in several ways:
  1. All early-bound object references are resolved to their CLSIDs (11),
and the type library is used to perform syntax checking of all property and
method calls.
  2. Once checked, the type library is again used to resolve the vTable
offsets for all called properties and methods. In this way, the object type
is specified, the method calls are verified against the specified interface,
and the most efficient binding is setup, all before runtime. Since VBA is
interpreted, this often happens just-in-time, but the conceptual workings
are identical to its compiled sibling.

RUNTIME OBJECT ACTIVATION
Lastly, we will touch on COM object activation to get a feel for how objects
get created at runtime.
  The information for the particulars of the class, (it's server file name
and location, associated type libraries, etc) are stored in the Registry,
and keyed by the CLSID. The server (a DLL, EXE, or OCX file) for a class
contains not only the code to perform the methods, but also contains a class
factory object, which houses the code used by the COM runtime to instantiate
objects in that class.
  Runtime object creation, early-bound, typically goes like this (1):
  1. Client requests a new instance of COM object
  2. The COM runtime looks up the associated server DLL from the Registry
using the object's CLSID, and loads it into memory.
  3. The COM runtime then retrieves the requested class from the DLL. What
it gets back is a reference to the Class Factory object, which uses the
IClassFactory interface. Next, it calls the CreateInstance method to create
the actual object instance in memory.
  4. Finally, the COM runtime gets the requested interface from the object,
and returns a reference to it back to the client. Its work done, the COM
runtime drops out of the picture, and client and object communicate
directly.
  So this quick look at COM activation demonstrates the role of the Registry
and CLSIDs in locating and creating objects. Even for late-bound
instantiation, the registry is used, but when the CLSID isn't known, the
ProgID, or fully qualified class name, is used instead (11).

References
==========

I've covered a lot of ground quickly in this post. These resources are for
the reader interested in finding out more:

1. Introduction to COM
http://arcobjectsonline.esri.com/ArcObjectsOnline/GettingStarted/IntroToCOM.
htm

2. Effective Visual Basic: How to Improve Your VB/COM+ Applications,
Addison-Wesley

3. KB 245115 -- INFO: Using Early Binding and Late Binding in Automation
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q245115

4. KB 138138 -- INFO: Late, ID, Early Binding Types Possible in VB for Apps
http://support.microsoft.com/default.aspx?scid=kb;EN-US;138138

5. How Visual Basic COM+ Objects Work Internally
http://www.windowsdevcenter.com/pub/a/oreilly/windows/news/mojica_1000.html

6. An Under-the-Covers Look at OLE
http://www.avdf.com/aug96/art_ole.html

7. Creating a Reference to an Object
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/htm
l/vbconassigningreferencetoactivexcomponentobject.asp

8. How Binding Affects ActiveX Component Performance
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/htm
l/vbconhowbindingaffectsolecomponentperformance.asp

9. Speeding Object References
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon98/htm
l/vbconspeedingobjectreferences.asp

10. KB 247579 -- INFO: Use DISPID Binding to Automate Office Applications
Whenever Possible
http://support.microsoft.com/default.aspx?scid=kb;EN-US;247579

11. CCRP Versioning Policy: New ProgIDs Used for Visual Basic Version Builds
http://ccrp.mvps.org/index.html?support/faqs/progid.htm

--
_______________________________________________
AccessD mailing list
AccessD at databaseadvisors.com
http://databaseadvisors.com/mailman/listinfo/accessd
Website: http://www.databaseadvisors.com




More information about the AccessD mailing list