哪个更快? ByVal 还是 ByRef?
In VB.NET, which is faster to use for method arguments, ByVal
or ByRef
?
Also, which consumes more resources at runtime (RAM)?
I read through this question, but the answers are not applicable or specific enough.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Byval 和 ByRef 参数的使用应基于需求和对它们如何工作的了解,而不是基于速度。
http://www.developer.com/net/vb/article.php/3669066
回应 Slough 的评论 -
哪个在运行时消耗更多资源?
参数在堆栈上传递。 堆栈非常快,因为它的内存分配只是一个指针增量来保留新的“帧”或“分配记录”。 大多数 .NET 参数不会超过机器寄存器的大小,如果使用任何“堆栈”空间来传递参数,那么就很小。 事实上,基本类型和指针都是在堆栈上分配的。 .NET 中的堆栈大小限制为 1 MB。 这应该可以让您了解参数传递消耗的资源有多少。
您可能会发现这一系列文章很有趣:
通过堆栈分配提高性能(.NET 内存管理:第 2 部分)
哪个更快? ByVal 或 ByRef。
准确和完美地测量是很困难的 - 取决于测量的上下文,但我编写的调用方法 1 亿次的基准得出以下结果:
注释每个方法中的变量和赋值 -
我们可以得出结论,传递引用类型(字符串、类)ByVal 将节省一些时间。 您可能还会说传递值类型(整数、字节)-ByVal 会节省一些时间。
同样,在宏伟的计划中,时间可以忽略不计。 更重要的是正确使用 ByVal 和 ByRef 并了解“幕后”发生的事情。 在例程中实现的算法肯定会多次影响程序的运行时间。
Byval and ByRef arguments should be used based on requirements and knowledge of how they work not on speed.
http://www.developer.com/net/vb/article.php/3669066
In response to a comment by Slough -
Which consumes more resources at runtime?
Parameters are passed on the stack. The stack is very fast, because its memory allocation is simply a pointer increment to reserve a new "frame" or "allocation record." Most .NET parameters do not exceed the size of a machine register so little if any "stack" space is used to pass parameters. In fact basic types and pointers are both allocated on the stack. The stack size in .NET is limited to 1 MB. This should give you an idea of how few resources are consumed by parameter passing.
You may find this series of articles interesting:
Improving Performance Through Stack Allocation (.NET Memory Management: Part 2)
Which is faster? ByVal or ByRef.
It is difficult at best to measure accurately and fairy - depending on the context of your measurement, but a benchmark I wrote calling a method 100 million times came up with the following:
Commenting out the variable and assignment in each method -
One could conclude that passing reference types (strings, classes) ByVal will save some time. You might also say that passing value types (integer, byte) - ByVal will save some time.
Again the time is negligible in the grand scheme of things. What's more important is using ByVal and ByRef properly and understanding what's going on "behind the scenes." The algorithms implemented in your routines will most surely affect the runtime of your program many times more.
如果您使用非常大的值类型(例如 Guid 相当大),则通过引用传递参数可能会稍微快一些。 在其他情况下,当您通过引用传递而不是通过值传递时,可能会出现更多复制等 - 例如,如果您有一个字节参数,那么一个字节显然小于四个或八个字节如果您通过引用传递指针,则该指针将采用该指针。
实际上,您几乎不必担心这一点。 编写尽可能可读的代码,这几乎总是意味着通过值而不是引用传递参数。 我很少使用 ByRef。
如果您想提高性能并认为 ByRef 会对您有所帮助,请在投入使用之前仔细对其进行基准测试(根据您的实际情况)。
编辑:我在另一个(之前已接受,现在已删除)答案的评论中注意到,对于值类型时 ByRef 与 ByVal 的含义存在很多误解。 我有一篇关于参数传递的文章,多年来它很受欢迎 - 它是用 C# 编写的术语,但相同的概念也适用于 VB.NET。
If you're using a very large value type (Guid is pretty big, for example) it may be very slightly faster to pass a parameter by reference. In other cases, there may be more copying etc when you pass by reference than by value - for instance, if you've got a byte parameter, then one byte is clearly less than the four or eight bytes that the pointer would take if you passed it by reference.
In practice, you should almost never worry about this. Write the most readable code possible, which almost always means passing parameters by value instead of reference. I use ByRef very rarely.
If you want to improve performance and think that ByRef will help you, please benchmark it carefully (in your exact situation) before committing to it.
EDIT: I note in the comments to another (previously accepted, now deleted) answer that there's a great deal of misunderstanding about what ByRef vs ByVal means when it comes to value types. I have an article about parameter passing which has proved popular over the years - it's in C# terminology, but the same concepts apply to VB.NET.
这取决于。 如果您传递一个对象,那么它已经在传递一个指针。 这就是为什么如果你传入一个 ArrayList(例如)并且你的方法向 ArrayList 添加一些东西,那么调用代码也会将相同的对象放入传入的 ArrayList 中,因为它是相同的 ArrayList。 唯一不传递指针的情况是,将具有内部数据类型(例如 int 或 double)的变量传递到函数中时。 此时,它会创建一个副本。 然而,这些对象的数据量非常小,因此在内存使用或执行速度方面几乎不会产生任何影响。
It depends. If you are passing an object, it is already passing a pointer. That's why if you pass in an ArrayList (for instance) and your method adds somthing to the ArrayList, then the calling code also has the same object into it's ArrayList, that was passed in, because it's the same ArrayList. The only time that it doesn't pass a pointer, is when you pass a variable with an intrinsic data type, like an int, or a double, into the function. At that point, it creates a copy. However, the data size of these objects is so small, that it would hardly make a difference either way, in terms of memory usage or speed of execution.
如果传递引用类型,ByRef 会更慢。
这是因为传入的是一个指向指针的指针。 对对象上字段的任何访问都需要取消引用额外的指针,这将需要一些额外的时钟周期才能完成。
如果要传递值类型,那么如果结构有许多成员,则 byref 可能会更快,因为它只传递单个指针,而不是复制堆栈上的值。 在访问成员方面,byref 会更慢,因为它需要进行额外的指针取消引用(sp->pValueType->member 与 sp->member)。
大多数时候在 VB 中您不必担心这一点。
在 .NET 中,很少有具有大量成员的值类型。 它们通常很小。 在这种情况下,传递值类型与向过程传递多个参数没有什么不同。 例如,如果您有按值传入 Point 对象的代码,那么它的性能将与采用 X 和 Y 值作为参数的方法相同。 看到 DoSomething(x 作为整数,y 作为整数) 可能不会引起性能问题。 事实上,你可能永远不会三思而后行。
如果您自己定义大值类型,那么您可能应该重新考虑将它们转换为引用类型。
唯一的其他区别是执行代码所需的指针间接数量的增加。 您很少需要在该级别进行优化。
大多数时候,要么存在您可以解决的算法问题,要么您的性能瓶颈与 IO 相关,例如等待数据库或写入文件,在这种情况下,消除指针间接对您没有多大帮助。
因此,我建议您不要关注 byval 或 byref 是否更快,而应该真正关注为您提供所需语义的内容。 一般来说,除非您特别需要 byref,否则最好使用 byval。 它使程序更容易理解。
If you are passing in a reference type, ByRef is slower.
This is because what gets passed in is a pointer to a pointer. Any access to fields on the object requires dereferencing an extra pointer , which will take a few extra clock cycles to complete.
If you are passing a value type, then byref may be faster if the structure has many members, because it only passes a single pointer rather than copying the values on the stack. In terms of accessing members, byref will be slower because it needs to do an extra pointer dereference (sp->pValueType->member vs sp->member).
Most of the time in VB you shouldn't have to worry about this.
In .NET it is rare to have value types with a large number of members. They are usually small. In that case, passing in a value type is no different than passing in multiple arguments to a procedure. For example, if you had code that passed in a Point object by value, it's perf would be the same as a method that took X and Y values as parameters. Seeing DoSomething(x as integer, y as integer) would probably not cause perf concerns. In fact, you would probably never think twice about it.
If you are defining large value types your self, then you should probably reconsider turning them into reference types.
The only other difference is the increase in the number of pointer indirections required to execute the code. It is rare that you ever need to optimize at that level.
Most of the time, there are either algorithmic issues you can address, or your perf bottleneck is IO related, such as waiting for a database or writing to a file, in which case eliminating pointer indirections isn't going to help you much.
So, instead of focusing on wheter byval or byref is faster, I would recommend that you should really be focusing on what gives you the semantics that you need. In general, it's good idea to use byval unless you specifically need byref. It makes the program much easier to understand.
虽然我对 .NET 的内部了解不多,但我将讨论我对编译语言的了解。 这不适用于引用类型,并且对于值类型可能不完全准确。 如果您不知道值类型和引用类型之间的区别,则不应阅读本文。 我假设 32 位 x86(带有 32 位指针)。
结论:
了解 ByVal 和 ByRef 实际为您做什么以及了解值类型和引用类型之间的差异比考虑性能更重要。 第一条规则是使用更适合您的代码的方法。
对于大值类型(超过 64 位),请按引用传递,除非按值传递有优势(例如更简单的代码、“它只是有意义”或接口一致性)。
对于较小的值类型,传递机制对性能没有太大影响,而且无论如何,很难预测哪种方法会更快,因为它取决于对象大小、调用者和被调用者如何使用对象,甚至缓存考虑因素。 只做对你的代码有意义的事情。
While I don't know much about the internals of .NET, I'll discuss what I know about compiled languages. This does not apply to reference types, and may not be completely accurate about value types. If you don't know the difference between value types and reference types, you shouldn't read this. I'll assume 32-bit x86 (with 32-bit pointers).
The verdict:
It's much more important to understand what ByVal and ByRef actually do for you, and understand the difference between value and reference types, than to think about performance. The number one rule is to use whichever method is more appropriate to your code.
For large value types (more than 64 bits), pass by reference unless there is an advantage to passing by value (such as simpler code, "it just makes sense", or interface consistency).
For smaller value types, the passing mechanism doesn't make much difference to performance, and anyway it's hard to predict which method will be faster, since it depends on the object size, how the caller and callee use the object, and even cache considerations. Just do whatever makes sense for your code.
ByVal
创建变量的副本,而ByRef
传递指针。 因此,我想说 ByVal 速度较慢(由于复制需要时间)并且使用更多内存。ByVal
creates a copy of the variable, whereasByRef
passes a pointer. I would therefore say thatByVal
is slower (due to time it takes to copy) and uses more memory.我的好奇心是检查取决于对象和内存使用情况的不同行为
结果似乎表明 ByVal 总是获胜,资源取决于是否收集内存或更少(仅限 4.5.1)
My curiosity was to check the different behaviours depending object and memory usages
The result seems demostrate that ByVal always wins, the resource depends if collect memory or less (4.5.1 only)