Results 1 to 18 of 18

Thread: What does the With statement do internally?

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Apr 2019
    Posts
    67

    What does the With statement do internally?

    Hi All,

    What I know:
    * Using with speeds up developement
    * Using with makes code a lot easier to manage.
    * Using with can make code prettier


    I think "With ... End With" speeds up execution time, which is something I've seen posted before. But I've also seen in other posts that it's a pure syntactic sugar and does nothing to compiled code. I've also heard:

    With speeds up execution because objects need to be "opened" before they are accessed, and "closed" afterwards to allow other processes to access them.

    Looking through the COM Api's the only thing I could see which might relate to this is CoLockObjectExternal.

    So my question is, for the following code:

    Code:
    With A.B.C
       With .D
          Debug.Print .E
       end with
       Debug.Print .F & .G
    End With
    What does VB6 do internally? E.G. is it like this:

    Code:
    set temp1 = A.B.C
    set temp2 = temp1.D
    Debug.Print temp2.E
    Debug.print temp1.F & temp1.G
    or is it more complex like:

    Code:
    set temp1 = A.B.C
    CoLockObjectExternal temp1
    
    set temp2 = temp1.D
    CoLockObjectExternal temp2
    
    Debug.Print temp2.E
    Debug.print temp1.F & temp1.G
    
    CoDisconnectObject temp2
    CoDisconnectObject temp1
    Does anyone know the answer?

  2. #2
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: What does the With statement do internally?

    No, CoLockObjectExternal and CoDisconnectObject are 100% not involved in With construction. Calling methods on an interface does not need wrapping the call in AddRef/Release too so nothing to skip/remove from normal code per se.

    The only optimization is that With uses a hidden local variable for the expression which is used for calls inside its scope. For instance if there is a member variable m_oData in a class, using With m_oData declares and initializes a hidden local variable (on the stack) which is used instead when making calls to "instanceless" methods inside the With scope. This optimizes having to retrieve m_oData from object data (the so called Me in VB parlance) on each call.

    There you have it -- a small victory. The more complex the expression is, the more CPU cycles are saved on calls inside the With scope.

    cheers,
    </wqw>

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Apr 2019
    Posts
    67

    Re: What does the With statement do internally?

    Quote Originally Posted by wqweto View Post
    The only optimization is that With uses a hidden local variable for the expression which is used for calls inside its scope. For instance if there is a member variable m_oData in a class, using With m_oData declares and initializes a hidden local variable (on the stack) which is used instead when making calls to "instanceless" methods inside the With scope. This optimizes having to retrieve m_oData from object data (the so called Me in VB parlance) on each call.
    Interesting so if I have you correct, if I did:

    Code:
    With A
      .B=1
      .C=2
      .D=3
    End With
    has no performance benefits over

    Code:
    A.B=1
    A.C=2
    A.D=3
    ?

  4. #4
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: What does the With statement do internally?

    Quote Originally Posted by sancarn View Post
    has no performance benefits over

    Code:
    A.B=1
    A.C=2
    A.D=3
    ?
    If A is a member variable there *are* performance benefits. With statement is transformed to this

    Code:
    Dim __hidden_A As __TypeOfA
    Set __hidden_A = A
    __hidden_A.B = 1
    __hidden_A.C = 2
    __hidden_A.D = 3
    Because __hidden_A is on the stack while A is actually this->A (a member variable) there are several instructions (or more) saved.

    cheers,
    </wqw>

  5. #5
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: What does the With statement do internally?

    Yeah, the big payoff is stuff like:

    Code:
    With DataEnvironment1.rsCommand1.Fields.Item(0)
        ...several statements using the item...
    End With

  6. #6

    Thread Starter
    Lively Member
    Join Date
    Apr 2019
    Posts
    67

    Re: What does the With statement do internally?

    Quote Originally Posted by wqweto View Post
    If A is a member variable there *are* performance benefits. With statement is transformed to this

    Code:
    Dim __hidden_A As __TypeOfA
    Set __hidden_A = A
    __hidden_A.B = 1
    __hidden_A.C = 2
    __hidden_A.D = 3
    Because __hidden_A is on the stack while A is actually this->A (a member variable) there are several instructions (or more) saved.

    cheers,
    </wqw>
    it took me a while to understand what you meant by member lol, but i see now yes that would make a lot of sense. I more so meant in the case where A is a local variable I.E.

    Code:
    Sub test
      Dim A as Whatever
      set A = new Whatever
      With A
        .B = 1
        .C = 2
        .D=3
      end with
    end sub
    in this instance I would expect a small performance decrease because A has to be moved from it's local variable location to the special hidden variable location. But the performance decrease will likely be negligible...

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: What does the With statement do internally?

    Quote Originally Posted by sancarn View Post
    But the performance decrease will likely be negligible...
    Yes and it might even be worth it if this removes visual clutter in the source code. I'm willing to use With on local UDTs as well if it reduces source code lines length and/or prevents code lines from splitting.

    cheers,
    </wqw>

  8. #8
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,728

    Re: What does the With statement do internally?

    I also like to use "With New" when something is just needed for a quick time and thus want to save a variable declaration. (kind of lazy style, but reduces source code length)
    It's certainly also faster in theory. (IUnknown::AddRef and IUnknown::Release just called one time)

    Code:
    With New Whatever
    [...]
    End With

  9. #9
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: What does the With statement do internally?

    Or "With CreateObject()" for things like ADOX that I don't want to early-bind to but only need for a few operations.

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: What does the With statement do internally?

    I need to read all the responses, but I suspect the With statement does very little internally. My guess would be that it declares a temporary object variable of the Type of the With object, sets that object variable (i.e., creates a new reference), and then uses it within the "With" block. I suspect that 99% of that (if not 100%) is actually done by the compiler, and has nothing to do with anything runtime.

    In fact, regarding actual code, I suspect the following two blocks of code are identical:

    Code:
    
        Dim c As Collection
        Set c = New Collection
    
        With c
            .Add "asdf"
            .Add "qwer"
            .Add "zxcv"
        End With
    
    
    Code:
    
        Dim c As Collection
        Set c = New Collection
    
        c.Add "asdf"
        c.Add "qwer"
        c.Add "zxcv"
    
    In this case, the "With" block buys us very little. However, if we're digging deep into some object hierarchy (like I often am when doing Word or Excel automation), the "With" approach is quite convenient for not having to dig through that hierarchy. And, according to MS, it's faster when we've got such a hierarchy, as each piece of the hierarchy doesn't have to be resolved each time.

    But, we could still accomplish the same thing by explicitly declaring an object variable that represented the end-point of our object hierarchy, and explicitly setting that reference and using it. So, in the end, the "With" block is just a nice convenience.

    Best Regards,
    Elroy

    p.s. I look forward to anyone spotting anything wrong with what I've said.

    EDIT: For grins, here's an example where it's actually useful. But again, I could have created a new object variable and set it to "doc.ActiveWindow.ActivePane.Selection" and accomplished the same thing:

    Code:
    
    Public Sub InWordTurnLineColor(doc As Object, TextColor As Long, Optional iSkipWordsAtBeg As Long)
        With doc.ActiveWindow.ActivePane.Selection
            .HomeKey wdLine, wdMove                                              ' Move to beginning of line.
            If iSkipWordsAtBeg Then .MoveRight wdWord, iSkipWordsAtBeg, wdMove   ' Skip over notation of joint (or just tabs).
            .EndKey wdLine, wdExtend                                             ' Select text to end of line.
            .Font.Color = TextColor                                              ' Turn the selection a color.
        End With
    End Sub
    
    
    Last edited by Elroy; Aug 14th, 2020 at 11:18 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  11. #11
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: What does the With statement do internally?

    Compile both ways and disassemble the binary. In some simple cases the object reference stays cached in a register. Most of the time that isn't practical though (calculations, function calls, etc.) so it doesn't happen.

  12. #12
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: What does the With statement do internally?

    Ahhh, I actually read all the posts, and they're interesting.

    For one, I'd never considered using "With New" before. Krool, that's a neat trick, and I can see how it could come in handy on occasion.

    So, just to be clear, y'all are thinking that ...

    Code:
    
    Public Sub InWordTurnLineColor(doc As Object, TextColor As Long, Optional iSkipWordsAtBeg As Long)
        With doc.ActiveWindow.ActivePane.Selection
            .HomeKey wdLine, wdMove                                              ' Move to beginning of line.
            If iSkipWordsAtBeg Then .MoveRight wdWord, iSkipWordsAtBeg, wdMove   ' Skip over notation of joint (or just tabs).
            .EndKey wdLine, wdExtend                                             ' Select text to end of line.
            .Font.Color = TextColor                                              ' Turn the selection a color.
        End With
    End Sub
    
    ... is faster than ...

    Code:
    
    Public Sub InWordTurnLineColor(doc As Object, TextColor As Long, Optional iSkipWordsAtBeg As Long)
        Dim DocText As Object
        Set DocText = doc.ActiveWindow.ActivePane.Selection
        '
        DocText.HomeKey wdLine, wdMove                                              ' Move to beginning of line.
        If iSkipWordsAtBeg Then DocText.MoveRight wdWord, iSkipWordsAtBeg, wdMove   ' Skip over notation of joint (or just tabs).
        DocText.EndKey wdLine, wdExtend                                             ' Select text to end of line.
        DocText.Font.Color = TextColor                                              ' Turn the selection a color.
    End Sub
    
    
    ... ?

    p.s. I know I get into some late vs early binding issues, but I suspect my example is ALL late binding, even if "With" is used.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  13. #13
    PowerPoster dilettante's Avatar
    Join Date
    Feb 2006
    Posts
    24,487

    Re: What does the With statement do internally?

    I would think the late-binding costs you more than anything else.

    So faster, but not by much. Even is good cases it only helps performance in code that executes a ton of times.

    But it does clean up that "newb codez" look of not using it.

  14. #14
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: What does the With statement do internally?

    Just FYI, per MSDN

    Note: Once a With block is entered, object can't be changed. As a result, you can't use a single With statement to affect a number of different objects.

    You can nest With statements by placing one With block within another. However, because members of outer With blocks are masked within the inner With blocks, you must provide a fully qualified object reference in an inner With block to any member of an object in an outer With block

    In general, it's recommended that you don't jump into or out of With blocks. If statements in a With block are executed, but either the With or End With statement is not executed, a temporary variable containing a reference to the object remains in memory until you exit the procedure.
    Edited. One of my biggest "abuses" of WITH is for loading properties on some controls and recordsets, especially listviews
    Code:
    With ListView1.ListIems.Add(, , , "Main Item Text")
        .SubItems(1) = ...
        .SubItems(2) = ...
        ... etc
    End With
    Last edited by LaVolpe; Aug 14th, 2020 at 11:49 AM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #15

    Thread Starter
    Lively Member
    Join Date
    Apr 2019
    Posts
    67

    Re: What does the With statement do internally?

    So I made a post on StackOverflow regarding what I learnt from here and ultimately got criticised from mods who, rightly, thought it was all speculation.

    So I actually started to do some analysis of the P-Code generated and actual performance analysis.

    Notes
    My performance tests were in VBA. VBA does have 2 compiling steps - Code to P-Code, and P-Code to Executable codes, however I'm unsure there is any optimisation step in the VBA compiler, where as the VB6 compiler might have one.


    [C]With A[/C] uses a member variable.

    The real surprising thing to me here is that optimisation was only really seen with

    Code:
    With X.O
       .A=1
       .B=2
       .C=3
    End With
    Member variables are faster to access directly, without with. Similarly local variables are faster to access directly, without with.

    Set of tests used for reference:

    Module1 Code:
    1. Public A As New Class1
    2.  
    3. Sub testPerf1() 'Mac: 2.547119140625   Win:  1.7734375
    4.     Dim t As Long: t = Timer
    5.     For i = 1 To 10 ^ 8
    6.         'With A
    7.         'End With
    8.     Next
    9.     Debug.Print Timer - t
    10.    
    11. End Sub
    12. Sub testPerf2() 'Mac: 8.01708984375    Win:  4.48828125
    13.     Dim t As Long: t = Timer
    14.     For i = 1 To 10 ^ 8
    15.         With A
    16.         End With
    17.     Next
    18.     Debug.Print Timer - t
    19. End Sub
    20. Sub testPerf3() 'Mac: 16.60302734375   Win:  7.0546875
    21.     Dim t As Long: t = Timer
    22.     For i = 1 To 10 ^ 8
    23.         With A.O
    24.         End With
    25.     Next
    26.     Debug.Print Timer - t
    27. End Sub
    28. Sub testPerf4()  'Mac: 29.68798828125   Win:  10.61328125
    29.     Dim t As Long: t = Timer
    30.     For i = 1 To 10 ^ 8
    31.         With A.O.O
    32.         End With
    33.     Next
    34.     Debug.Print Timer - t
    35. End Sub
    36.  
    37.  
    38.  
    39. Sub testPerf5()  'Mac: 21.048828125   Win:  9.21875
    40.     Dim t As Long: t = Timer
    41.     For i = 1 To 10 ^ 8
    42.         With A
    43.             .A = 1
    44.         End With
    45.     Next
    46.     Debug.Print Timer - t
    47. End Sub
    48. Sub testPerf6()  'Mac: 15.7978515625   Win: 6.8203125
    49.     Dim t As Long: t = Timer
    50.     For i = 1 To 10 ^ 8
    51.         A.A = 1
    52.     Next
    53.     Debug.Print Timer - t
    54. End Sub
    55.  
    56.  
    57. Sub testPerf7()  'Mac: 54.376953125   Win:  23.40625
    58.     Dim t As Long: t = Timer
    59.     For i = 1 To 10 ^ 8
    60.         With A
    61.             .A = 1
    62.             .B = 2
    63.             .C = 3
    64.         End With
    65.     Next
    66.     Debug.Print Timer - t
    67. End Sub
    68. Sub testPerf8()  'Mac: 47.9931640625   Win:  21.046875
    69.     Dim t As Long: t = Timer
    70.     For i = 1 To 10 ^ 8
    71.         A.A = 1
    72.         A.B = 2
    73.         A.C = 3
    74.     Next
    75.     Debug.Print Timer - t
    76. End Sub
    77.  
    78.  
    79.  
    80.  
    81.  
    82. Sub testPerf9()  'Mac: 21.39208984375   Win:  8.8046875
    83.     Dim t As Long: t = Timer
    84.     Dim X As Class1: Set X = New Class1
    85.     For i = 1 To 10 ^ 8
    86.         With X
    87.             .A = 1
    88.         End With
    89.     Next
    90.     Debug.Print Timer - t
    91. End Sub
    92. Sub testPerf10()  'Mac: 14.951171875   Win:  6.203125
    93.     Dim t As Long: t = Timer
    94.     Dim X As Class1: Set X = New Class1
    95.     For i = 1 To 10 ^ 8
    96.         X.A = 1
    97.     Next
    98.     Debug.Print Timer - t
    99. End Sub
    100.  
    101.  
    102. Sub testPerf11()  'Mac: 54.1591796875   Win:  22.8828125
    103.     Dim t As Long: t = Timer
    104.     Dim X As Class1: Set X = New Class1
    105.     For i = 1 To 10 ^ 8
    106.         With X
    107.             .A = 1
    108.             .B = 2
    109.             .C = 3
    110.         End With
    111.     Next
    112.     Debug.Print Timer - t
    113. End Sub
    114. Sub testPerf12()  'Mac: 45.330078125   Win:  19.203125
    115.     Dim t As Long: t = Timer
    116.     Dim X As Class1: Set X = New Class1
    117.     For i = 1 To 10 ^ 8
    118.         X.A = 1
    119.         X.B = 2
    120.         X.C = 3
    121.     Next
    122.     Debug.Print Timer - t
    123. End Sub
    124.  
    125.  
    126.  
    127.  
    128. Sub testPerf13()  'Mac: 44.78125   Win:  19.8828125
    129.     Dim t As Long: t = Timer
    130.     Dim X As Class1: Set X = New Class1
    131.     With X.O
    132.         For i = 1 To 10 ^ 8
    133.             .A = 1
    134.             .B = 2
    135.             .C = 3
    136.         Next
    137.     End With
    138.     Debug.Print Timer - t
    139. End Sub
    140. Sub testPerf14()  'Mac: 61.703125   Win:  25.3046875
    141.     Dim t As Long: t = Timer
    142.     Dim X As Class1: Set X = New Class1
    143.     For i = 1 To 10 ^ 8
    144.         With X.O
    145.             .A = 1
    146.             .B = 2
    147.             .C = 3
    148.         End With
    149.     Next
    150.     Debug.Print Timer - t
    151. End Sub
    152. Sub testPerf15()  'Mac: 90.3515625   Win:  31.109375
    153.     Dim t As Long: t = Timer
    154.     Dim X As Class1: Set X = New Class1
    155.     For i = 1 To 10 ^ 8
    156.         X.O.A = 1
    157.         X.O.B = 2
    158.         X.O.C = 3
    159.     Next
    160.     Debug.Print Timer - t
    161. End Sub
    162.  
    163.  
    164.  
    165.  
    166. Sub testPerf16()  'Mac: 57.28125   Win: 23.05078125
    167.     Dim t As Long: t = Timer
    168.     For i = 1 To 10 ^ 8
    169.         With A
    170.             .A = 1
    171.             .B = 2
    172.             .C = 3
    173.         End With
    174.     Next
    175.     Debug.Print Timer - t
    176. End Sub
    177. Sub testPerf17()  'Mac: 49.9375   Win:  20.140625
    178.     Dim t As Long: t = Timer
    179.     For i = 1 To 10 ^ 8
    180.         A.A = 1
    181.         A.B = 2
    182.         A.C = 3
    183.     Next
    184.     Debug.Print Timer - t
    185. End Sub
    186. Sub testPerf18()  'Mac: 57.4453125    Win:  22.421875
    187.     Dim t As Long: t = Timer
    188.     Dim X As Class1: Set X = New Class1
    189.     For i = 1 To 10 ^ 8
    190.         With X
    191.             .A = 1
    192.             .B = 2
    193.             .C = 3
    194.         End With
    195.     Next
    196.     Debug.Print Timer - t
    197. End Sub
    198. Sub testPerf19()  'Mac: 47.28125   Win:  19.234375
    199.     Dim t As Long: t = Timer
    200.     Dim X As Class1: Set X = New Class1
    201.     For i = 1 To 10 ^ 8
    202.         X.A = 1
    203.         X.B = 2
    204.         X.C = 3
    205.     Next
    206.     Debug.Print Timer - t
    207. End Sub
    208. Sub testPerf20()  'Mac:  56.64453125   Win:  22.96875
    209.     Dim t As Long: t = Timer
    210.     Dim X As Class1: Set X = A
    211.     For i = 1 To 10 ^ 8
    212.         With X
    213.             .A = 1
    214.             .B = 2
    215.             .C = 3
    216.         End With
    217.     Next
    218.     Debug.Print Timer - t
    219. End Sub
    220. Sub testPerf21()  'Mac: 46.79296875   Win: 19.8046875
    221.     Dim t As Long: t = Timer
    222.     Dim X As Class1: Set X = A
    223.     For i = 1 To 10 ^ 8
    224.         X.A = 1
    225.         X.B = 2
    226.         X.C = 3
    227.     Next
    228.     Debug.Print Timer - t
    229. End Sub
    230. Sub testPerf22()  'Mac: 100.15625   Win:  42.296875
    231.     Dim t As Long: t = Timer
    232.     Dim X As Class1: Set X = A
    233.     For i = 1 To 10 ^ 8
    234.         With X
    235.             .A = 1
    236.             .B = 2
    237.             .C = 3
    238.             .A = 1
    239.             .B = 2
    240.             .C = 3
    241.         End With
    242.     Next
    243.     Debug.Print Timer - t
    244. End Sub
    245. Sub testPerf23()  'Mac: 90.1015625   Win: ???
    246.     Dim t As Long: t = Timer
    247.     Dim X As Class1: Set X = A
    248.     For i = 1 To 510 ^ 8
    249.         X.A = 1
    250.         X.B = 2
    251.         X.C = 3
    252.         X.A = 1
    253.         X.B = 2
    254.         X.C = 3
    255.     Next
    256.     Debug.Print Timer - t
    257. End Sub
    258. Sub testPerf24()  'Mac: ???   Win: ???
    259.     Dim t As Long: t = Timer
    260.     Dim X As Class1: Set X = A
    261.     For i = 1 To 10 ^ 8
    262.         With X
    263.             .A = 1
    264.             .B = 2
    265.             .C = 3
    266.             .A = 1
    267.             .B = 2
    268.             .C = 3
    269.             .A = 1
    270.             .B = 2
    271.             .C = 3
    272.         End With
    273.     Next
    274.     Debug.Print Timer - t
    275. End Sub
    276. Sub testPerf25()  'Mac: ???   Win: ???
    277.     Dim t As Long: t = Timer
    278.     Dim X As Class1: Set X = A
    279.     For i = 1 To 510 ^ 8
    280.         X.A = 1
    281.         X.B = 2
    282.         X.C = 3
    283.         X.A = 1
    284.         X.B = 2
    285.         X.C = 3
    286.         X.A = 1
    287.         X.B = 2
    288.         X.C = 3
    289.     Next
    290.     Debug.Print Timer - t
    291. End Sub

    Class1 Code:
    1. Public A
    2. Public B
    3. Public C
    4. Public O As Class1
    5.  
    6.  
    7. Private Sub Class_Initialize()
    8.     Set O = Me
    9. End Sub


    Edit: One last thing - A really neat use of the with statement is for sentries. So if you ever have options that need to turn on and off in code this is quite useful:

    Optimiser.cls Code:
    1. Private bEnableEvents as boolean
    2. Private bScreenUpdating as boolean
    3. sub class_initialise()
    4.   'Apply change and save state:
    5.   bEnableEvents = Application.EnableEvents
    6.   bScreenUpdating = Application.ScreenUpdating
    7.   Application.EnableEvents = false
    8.   Application.ScreenUpdating = false
    9. end sub
    10. Private Sub Class_Terminate()
    11.   'Revert change
    12.   Application.EnableEvents = bEnableEvents
    13.   Application.ScreenUpdating = bScreenUpdating

    Module1 Code:
    1. With new Optimiser
    2.   '...
    3. End With
    Last edited by sancarn; Aug 16th, 2020 at 04:17 AM. Reason: An additional nice to have that I learnt while going through this ordeal

  16. #16
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    Re: What does the With statement do internally?

    Performance measurement is hard. Most of your tests have to be re-run for the VBA crowd on Windows and all of the VB6 forums members that compile to native x86 code.

    Some of the conclusions will probably not hold water as a result e.g. member variables vs with.

  17. #17

    Thread Starter
    Lively Member
    Join Date
    Apr 2019
    Posts
    67

    Re: What does the With statement do internally?

    Quote Originally Posted by wqweto View Post
    Performance measurement is hard. Most of your tests have to be re-run for the VBA crowd on Windows and all of the VB6 forums members that compile to native x86 code.

    Some of the conclusions will probably not hold water as a result e.g. member variables vs with.
    Yes. All these tests have been done in the VBA environment on both Mac and Windows. If someone could run these over VB6 P-Code and VB6 compiled native code this would be really useful! I will be quite interested.

    My understanding, from bontchev, is that VBA doesn't have an optimisation step. VBA appears to compile to P-Code on save, and then compile again to "Execodes" known as the "performance cache" which is system specific. All of this is stored on in the VBA Project file on windows. If this is the same process which VB6 code is compiled under I wouldn't be surprised... But the performance tests might show us otherwise...

    To get an understanding of how With statements affect all platforms/compilation environments would be most interesting .

    Another thing that I hadn't tried yet is my member variable was while testing the member of a Module rather than a class. Realistically I should compare it to the performance from within a class also.

  18. #18
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: What does the With statement do internally?

    I just tested in VB6, both as p-code and compiled.

    In my test, I used all early-binding. I just made five classes, all nested. I'll list them backwards:

    Here's Class5.cls:
    Code:
    
    Option Explicit
    
    Friend Function Test() As String
        Test = "asdfasdf"
    End Function
    
    
    Class4.cls:
    Code:
    
    Option Explicit
    
    Dim cls5 As New Class5
    
    Friend Function Class5() As Class5
        Set Class5 = cls5
    End Function
    
    Class3.cls:
    Code:
    
    Option Explicit
    
    Dim cls4 As New Class4
    
    Friend Function Class4() As Class4
        Set Class4 = cls4
    End Function
    
    Class2.cls:
    Code:
    
    Option Explicit
    
    Dim cls3 As New Class3
    
    Friend Function Class3() As Class3
        Set Class3 = cls3
    End Function
    
    And Class1.cls:
    Code:
    
    Option Explicit
    
    Dim cls2 As New Class2
    
    Friend Function Class2() As Class2
        Set Class2 = cls2
    End Function
    

    And here's the test code I put together in Form1. I also included my TimerEx.cls (not listed). It's all included in the little attached project:
    Code:
    
    Option Explicit
    Dim cls1 As New Class1
    
    
    Private Sub Form_Load()
        Me.AutoRedraw = True
        Me.Font.Size = 14
        Me.Font.Name = "Segoe UI"
        Me.Font.Bold = True
        '
        ' Get everything instantiated.
        Call cls1.Class2.Class3.Class4.Class5.Test
        Call TimerEx.Value
    
    
        Me.Print "Click me"
    End Sub
    
    
    Private Sub Form_Click()
    
        Me.Print "Working..."
        Me.Refresh
        DoTesting
    
    End Sub
    
    Private Sub DoTesting()
        Dim dStart  As Double
        Dim dStop   As Double
    
        Dim i       As Long
        Const cnt   As Long = 10000000
    
    
    
    
    
        dStart = TimerEx.Value
        For i = 1 To cnt
            Call cls1.Class2.Class3.Class4.Class5.Test
        Next
        dStop = TimerEx.Value
        Me.Print "Full reference each time: "; Format$(dStop - dStart, "#0.000000")
        Me.Refresh
    
    
    
    
        Dim cls5    As Class5
        Set cls5 = cls1.Class2.Class3.Class4.Class5
        '
        dStart = TimerEx.Value
        For i = 1 To cnt
            Call cls5.Test
        Next
        dStop = TimerEx.Value
        Me.Print "Using explicit shortcut reference: "; Format$(dStop - dStart, "#0.000000")
        Me.Refresh
    
    
    
    
        With cls1.Class2.Class3.Class4.Class5
            dStart = TimerEx.Value
            For i = 1 To cnt
                Call .Test
            Next
            dStop = TimerEx.Value
        End With
        Me.Print "Using ""With"" reference: "; Format$(dStop - dStart, "#0.000000")
        Me.Refresh
    
    
    
    End Sub
    
    
    ------------------

    I tested both as IDE p-code and compiled.

    Here's the p-code test:
    Name:  IDE.png
Views: 269
Size:  11.0 KB

    And here's compiled:
    Name:  Compiled.png
Views: 264
Size:  38.4 KB

    I ran both several times.

    Clearly, creating a short-cut reference speeds things up. However, creating an "explicit" shortcut versus the "implicit" shortcut you get with the With block seems to make no difference. I ran it several times, and the differences between implicit and explicit bounced back and forth, always being almost identical.

    EDIT: Crud!!! I just noticed I didn't do the With block correctly. I'll redo it.

    EDIT2: Ok, I fixed the With block and still got basically the same results. It was just the one line inside the loop. I changed it to:

    Code:
    
                Call .Test
    
    (I fixed it in the above too. And in the attachment.)
    Attached Files Attached Files
    Last edited by Elroy; Aug 16th, 2020 at 08:23 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width