I'm always going on about how I prefer late binding over early binding. So does that mean my code comes out slower than yours?
I found a nice article that actually checks whether late binding is slower than early binding. It found that late binding was only trivially slower. But you know I wouldn't be writing this if I didn't do some tests of my own anyway.
A new Timer function
That article mentioned a more accurate timing function than the one I'd been using (Timer). After some research, I decided to implement it myself. I won't be updating the previous tests, but from now on I'll be using the timeGetTime API. This makes my tests only slightly less unscientific.
To use it you simply add this declaration at the top of a module as follows:
Public Declare Function timeGetTime Lib "winmm.dll" () As Long
Early and Late Binding with Outlook
We'll start with Outlook. We need to create two Outlook.Application objects, one early and one late bound. First I (ugh) set a reference to the Outlook Object Library:

Now we'll need to loop through the creation of various Outlook objects. I included the creation of the Outlook.Application object into the overall time.
Sub TestEarlyLateBindingOutlook()
Dim i As Long
Dim startTimeEarly As Long
Dim endTimeEarly As Long
Dim startTimeLate As Long
Dim endTimeLate As Long
Dim msg As String
Dim olAppEarly As Outlook.Application
Dim olAppLate As Object ' Outlook.Application
Dim msgEarly As Outlook.MailItem
Dim msgLate As Object ' Outlook.MailItem
Const numberofloops As Long = 1000
' use early binding
startTimeEarly = timeGetTime
Set olAppEarly = CreateObject("Outlook.Application")
For i = 1 To numberofloops
Debug.Print olAppEarly.Version
Set msgEarly = olAppEarly.CreateItem(olMailItem)
Next i
endTimeEarly = timeGetTime
' destroy object so late binding doesn't have
' an existing object to reference
Set olAppEarly = Nothing
Set msgEarly = Nothing
' use late binding
startTimeLate = timeGetTime
Set olAppLate = CreateObject("Outlook.Application")
For i = 1 To numberofloops
Debug.Print olAppLate.Version
Set msgLate = olAppLate.CreateItem(0)
Next i
endTimeLate = timeGetTime
msg = "Using Early binding: " & _
(endTimeEarly - startTimeEarly) / 1000 & " seconds" & vbCrLf
msg = msg & "Using Late binding: " & _
(endTimeLate - startTimeLate) / 1000 & " seconds" & vbCrLf
MsgBox msg
End Sub
Because Outlook is a single-instance application, to prevent the late bound code from grabbing the existing instance, we destroy the object before doing our late bound test.
Results
We'll start with 1,000 iterations.

The late bound Outlook object is running slightly faster. Let's continue to 2,000 iterations:

The early bound Outlook object is running even slower now. At 5,000 iterations, the early bound object is about 2 seconds slower:

Finally, at 7,500 iterations, early binding is just over 11 seconds while late binding is just under eight:

I would love to hear that I'm doing this wrong, but it looks like late binding is faster. Ha! Take that, all you early binders!
Early and Late Binding with Access
Now I'll try to do this with Access. We'll create two databases, then read some simple properties. Based on the previous example, my assumption is that late binding will be faster than early binding.
As usual, we first manually set a reference to the Access Object Library:

Sub TestEarlyLateBindingAccess()
Dim i As Long
Dim startTimeEarly As Long
Dim endTimeEarly As Long
Dim startTimeLate As Long
Dim endTimeLate As Long
Dim msg As String
Dim accAppEarly As Access.Application
Dim accAppLate As Object ' Access.Application
Const numberofloops As Long = 1000
On Error Resume Next
Kill "C:\my_early_bound_database.mdb"
Kill "C:\my_late_bound_database.mdb"
On Error GoTo 0
' use early binding
startTimeEarly = timeGetTime
Set accAppEarly = CreateObject("Access.Application")
accAppEarly.DBEngine.CreateDatabase _
"C:\my_early_bound_database.mdb", ";LANGID=0x0409;CP=1252;COUNTRY=0"
For i = 1 To numberofloops
Debug.Print accAppEarly.Version
Debug.Print accAppEarly.ProductCode
Next i
endTimeEarly = timeGetTime
' use late binding
startTimeLate = timeGetTime
Set accAppLate = CreateObject("Access.Application")
accAppLate.DBEngine.CreateDatabase _
"C:\my_late_bound_database.mdb", ";LANGID=0x0409;CP=1252;COUNTRY=0"
For i = 1 To numberofloops
Debug.Print accAppLate.Version
Debug.Print accAppLate.ProductCode
Next i
endTimeLate = timeGetTime
msg = "Using Early binding: " & _
(endTimeEarly - startTimeEarly) / 1000 & " seconds" & vbCrLf
msg = msg & "Using Late binding: " & _
(endTimeLate - startTimeLate) / 1000 & _
" seconds" & vbCrLf
MsgBox msg
End Sub
Results
First we'll start out with 1,000 iterations. It looks like late binding is actually slower!

At 2,000 iterations late binding is still slower:

At 5,000 iterations, late binding looks like it is getting even slower. It takes 2.2 seconds for late binding to create a database and read some simple properties, while early binding is taking only 1.3 seconds.

Finally, at 7,500 iterations, it is still barely noticeable but early binding is definitely faster:

Conclusion
Although I will be sticking with late binding, there are clearly times when early binding is faster. I feel validated using late binding in my code but I still don't understand why it was faster with Outlook than with Access.
One lesson the article reminds us is that if you have to use an object's methods or properties in a loop, create the object outside the loop. If you have a function that needs an object, create the object in the calling procedure and pass it to the function. This way, if you need to call the function repeatedly, the object is only ever created once, minimizing the late binding time penalty (if any).
An example of this may be found on the MSXML Object Library page. The GetResponse function takes an existing XMLHTTP object as a parameter, so you would need to create this object in the calling function. This way, you can loop the GetResponse function, creating the XMLHTTP object only once and reusing it through each iteration of the loop.
Read more about binding at the revised Early and Late Binding page.
Hi,
Did you have your Outlook open when you started the test? As you state "Outlook is a single-instance application", so if you didn't then the early bound version would have had to actually create – ie start up Outlook, whilst the latebound version just had to "get" the object.
You'd need olAppEarly.quit to prevent that.
That said, a linear trend line on your results still suggest that late binding is a third quicker than early binding for outlook and if the above was the issue it wouldn't. But take this with a pinch of salt as well as the linear trend also gives a negative overhead forcreating the object for both early & late binding!
I'm not sure it matters. Either way, both sets of code have to get an instance of Outlook.Application. Whether Outlook happens to already be open or not would simply raise or lower the overall completion time of each loop.
I specifically addressed that in the code.
This may be a dumb question, but essentially the only difference between early binding and late binding is that early binding sets a reference to the Object Library manually before running any code?
Not exactly. You also need to declare your objects as a specific type, as opposed to 'As Object'.
Got it. Thanks, really appreciated this post.