Home All Groups Group Topic Archive Search About
Author
2 Jun 2005 10:08 PM
jroozee@gmail.com
Since using ByRef passes the memeory pointed to a variable, and ByVal
copies the variable.. Is it FASTER to use ByRef since your not causing
the CPU to create a new memory allocation for the same data?

If so, why would I ever want to use ByVal?

Thanks
Jason Roozee

Author
2 Jun 2005 10:54 PM
Jim Mack
jroo***@gmail.com wrote:
> Since using ByRef passes the memeory pointed to a variable, and ByVal
> copies the variable.. Is it FASTER to use ByRef since your not causing
> the CPU to create a new memory allocation for the same data?
>
> If so, why would I ever want to use ByVal?


Bad logic -- faulty first premise.  There's no 'since' in this, and speed is only one consideration.

It depends on what type of variable is being passed, and sometimes to what kind of procedure.

For example, passing a long integer byref pushes the (4-byte) address of the variable onto the stack.  In order to actually use the variable, the called proceduree must dereference it -- get the value from the address.  So there is one push, and one dereference.

Passing it byval causes vb to do the deref, and push the 4-byte value onto the stack.  The called procedure need do nothing else to use the value.  So here too there is one deref, and one push.

In neither case is there a copy of anything made.  It's neutral as far as speed goes.  The difference is that a variable passed byval can't be changed by the called proc, since its location is not known, only its value.  This is (almost always) a Good Thing.

The same analysis holds for any scalar variable of 4 bytes or less (byte, short, single, long).

For longer scalars (double, currency) it's a little bit more involved, but in real life you would have to do a whole lot of passing to see much difference -- the overhead of the call itself overwhelms the couple of cycles needed to deref another dword.

Objects, arrays and UDTs are always passed byref, if only (but not only) because the size of the data tips the speed factor in favor of that.  Marshalled values (those passed out of process) go though a whole different, ah, process.

Strings are a different story.  Passing a string ByVal to a VB procedure _does_ result in a copy, because a string is essentially a pointer, and passing it 'byval' would still leave the value unprotected.  Here passing byref is clearly a winner, unless you absolutely need the protection.

Passing a string to a Declared external procedure involves a conversion from Unicode to MBCS, so there is a copy of sorts, but the value is not protected because any changes made to the copy are reflected back into the original Unicode string.  Byref here is a loser, since it just passes the address of the address of the copy -- for no benefit -- and 99% of external procedures couldn't deal with that anyway.

There's more, but that's most of it.

--

    Jim Mack
    MicroDexterity Inc
    www.microdexterity.com
Author
3 Jun 2005 10:15 AM
Tony Proctor
....also, if you're talking to an out-of-process component then ByVal is
always best. This is because ByVal doesn't accommodate the possibility of
write-back through the arguments and so the marshalling is substantially
simpler.

        Tony Proctor

"Jim Mack" <jmack@mdxi.nospam.com> wrote in message
news:eCGeQY8ZFHA.3356@TK2MSFTNGP15.phx.gbl...
jroo***@gmail.com wrote:
> Since using ByRef passes the memeory pointed to a variable, and ByVal
> copies the variable.. Is it FASTER to use ByRef since your not causing
> the CPU to create a new memory allocation for the same data?
>
> If so, why would I ever want to use ByVal?


Bad logic -- faulty first premise.  There's no 'since' in this, and speed is
only one consideration.

It depends on what type of variable is being passed, and sometimes to what
kind of procedure.

For example, passing a long integer byref pushes the (4-byte) address of the
variable onto the stack.  In order to actually use the variable, the called
proceduree must dereference it -- get the value from the address.  So there
is one push, and one dereference.

Passing it byval causes vb to do the deref, and push the 4-byte value onto
the stack.  The called procedure need do nothing else to use the value.  So
here too there is one deref, and one push.

In neither case is there a copy of anything made.  It's neutral as far as
speed goes.  The difference is that a variable passed byval can't be changed
by the called proc, since its location is not known, only its value.  This
is (almost always) a Good Thing.

The same analysis holds for any scalar variable of 4 bytes or less (byte,
short, single, long).

For longer scalars (double, currency) it's a little bit more involved, but
in real life you would have to do a whole lot of passing to see much
difference -- the overhead of the call itself overwhelms the couple of
cycles needed to deref another dword.

Objects, arrays and UDTs are always passed byref, if only (but not only)
because the size of the data tips the speed factor in favor of that.
Marshalled values (those passed out of process) go though a whole different,
ah, process.

Strings are a different story.  Passing a string ByVal to a VB procedure
_does_ result in a copy, because a string is essentially a pointer, and
passing it 'byval' would still leave the value unprotected.  Here passing
byref is clearly a winner, unless you absolutely need the protection.

Passing a string to a Declared external procedure involves a conversion from
Unicode to MBCS, so there is a copy of sorts, but the value is not protected
because any changes made to the copy are reflected back into the original
Unicode string.  Byref here is a loser, since it just passes the address of
the address of the copy -- for no benefit -- and 99% of external procedures
couldn't deal with that anyway.

There's more, but that's most of it.

--

    Jim Mack
    MicroDexterity Inc
    www.microdexterity.com
Author
3 Jun 2005 8:13 PM
Jim Mack
Tony Proctor wrote:
> ...also, if you're talking to an out-of-process component then ByVal
> is always best. This is because ByVal doesn't accommodate the
> possibility of write-back through the arguments and so the
> marshalling is substantially simpler.
>
>         Tony Proctor

Right, that's part of the "...there's more...".  Also, of course, you can't literally pass out-of-process byref, since the reference has meaning only within the sending process.  More, I'm sure, than the OP really wanted to know. :-)

--
        Jim
Author
2 Jun 2005 10:55 PM
Ken Halter
<jroo***@gmail.com> wrote in message
news:1117750094.738462.3690@g47g2000cwa.googlegroups.com...
> Since using ByRef passes the memeory pointed to a variable, and ByVal
> copies the variable.. Is it FASTER to use ByRef since your not causing
> the CPU to create a new memory allocation for the same data?
>
> If so, why would I ever want to use ByVal?
>
> Thanks
> Jason Roozee

ByRef should be faster but... ByVal is handy. It'll ignore data types during
compile, for one thing...

ByVal is also handy if you don't want to ensure that the data you're passing
won't be modified in the sub/function you're calling....
'=========
Option Explicit

Private Sub Test1(ByRef Arg As Long)
   Debug.Print Arg
   Arg = 1234 'modify the variable that was passed
End Sub

Private Sub Test2(ByVal Arg As Long)
   Debug.Print Arg
   Arg = 1234 'this ignored if ByVal
End Sub

Private Sub Form_Load()
   Dim i As Integer

   i = 12

   Call Test1(i) 'this won't compile (wrong data type)
   Debug.Print i 'well... if it were the correct type, i would = 1234

   Call Test2(i) 'no problem here
   Debug.Print i 'i still = 12 even though the sub set it to 1234

End Sub
'=========

--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..
Author
2 Jun 2005 11:51 PM
jroozee@gmail.com
Jim/Ken,
Thanks for the great info. You answered exactly what I was looking
for. I've always been using ByVal for all variables, and ByRef for
Arrays and Objects. Except, I'll use a ByRef when I want a procedure to
modify the varaible.

I just wasn't sure that in the case of a string variable if it would be
faster to use ByRef in all cases. Now I know.

Thanks!

Jason
Author
3 Jun 2005 2:42 AM
Jeff Johnson [MVP:VB]
"Ken Halter" <Ken_Halter@Use_Sparingly_Hotmail.com> wrote in message
news:%23Bf7gY8ZFHA.2940@tk2msftngp13.phx.gbl...

> ByVal is also handy if you don't want to ensure that the data you're
> passing won't be modified in the sub/function you're calling....

For posterity: remove the "don't" when reading this.
Author
3 Jun 2005 2:20 PM
Ken Halter
"Jeff Johnson [MVP:VB]" <i.get@enough.spam> wrote in message
news:Ol8eZX%23ZFHA.3356@TK2MSFTNGP15.phx.gbl...
>
>
> For posterity: remove the "don't" when reading this.

Jeezzzzz... side-tracked mid sentence. I didn't not mean to add the "do" vs
Show quoteHide quote
"don't" <g>


--
Ken Halter - MS-MVP-VB - http://www.vbsight.com
DLL Hell problems? Try ComGuard - http://www.vbsight.com/ComGuard.htm
Please keep all discussions in the groups..