当前位置:  开发笔记 > 编程语言 > 正文

哪个更快?ByVal还是ByRef?

如何解决《哪个更快?ByVal还是ByRef?》经验,为你挑选了4个好方法。

在VB.NET中,哪个更快用于方法参数,ByVal或者ByRef

此外,它在运行时(RAM)消耗更多资源?


我仔细阅读了这个问题,但答案不适用或不够具体.



1> user50612..:

Byval和ByRef参数应该根据它们如何工作而不是速度的要求和知识来使用.

http://www.developer.com/net/vb/article.php/3669066

回应斯劳的评论 -

哪个在运行时消耗更多资源?

参数在堆栈上传递.堆栈非常快,因为它的内存分配只是一个指针增量,用于保留新的"帧"或"分配记录".大多数.NET参数都不超过机器寄存器的大小,如果使用任何"堆栈"空间来传递参数那么少.实际上,基本类型和指针都在堆栈上分配..NET中的堆栈大小限制为1 MB.这可以让您了解参数传递消耗的资源很少.

您可能会发现这一系列文章很有趣:

通过堆栈分配提高性能(.NET内存管理:第2部分)

哪个更快?ByVal或ByRef.

根据你的测量环境,很难准确地测量和精灵测量,但是我写了一个基准,用一个方法调用了1亿次,得出以下结论:

参考类型 - 通过ByRef:420毫秒

参考类型 - 通过ByVal:382 ms

值类型 - 通过ByRef:421 ms

值类型 - 通过ByVal:416毫秒

Public Sub Method1(ByRef s As String)
    Dim c As String = s
End Sub

Public Sub Method2(ByVal s As String)
    Dim c As String = s
End Sub

Public Sub Method3(ByRef i As Integer)
    Dim x As Integer = i
End Sub

Public Sub Method4(ByVal i As Integer)
    Dim x As Integer = i
End Sub

Sub Main()

    Dim s As String = "Hello World!"
    Dim k As Integer = 5

    Dim t As New Stopwatch

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method1(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method2(s)
    Next
    t.Stop()

    Console.WriteLine("Reference Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method3(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()
    For i As Integer = 0 To 100000000
        Method4(i)
    Next
    t.Stop()

    Console.WriteLine("Value Type - ByVal " & t.ElapsedMilliseconds)

    Console.ReadKey()

End Sub

在每种方法中注释掉变量和赋值 -

参考类型 - 通过ByRef:389 ms

参考类型 - 通过ByVal:349毫秒

值类型 - 通过ByRef:416毫秒

值类型 - 通过ByVal:385毫秒

可以得出结论,传递引用类型(字符串,类)ByVal将节省一些时间.您可能还会说传递值类型(整数,字节) - ByVal将节省一些时间.

在宏伟的计划中,时间可以忽略不计.更重要的是正确使用ByVal和ByRef并了解"幕后"的情况.在您的例程中实现的算法肯定会多次影响程序的运行时间.


不幸的是,今天没有留下任何选票 - 但除此之外,我还没有获得大奖.
传递值类型"ByVal"所需的时间将根据所讨论的值类型的大小而变化.通过`ByRef`所需的时间不会.如果值类型很大,传递`ByRef`可能会快得多.请注意,即使非常大的值类型(数千个字节)也可以非常高效,如果可以避免通过值传递它们或者不必要地复制它们.
这儿这儿.如果你想通过改变它来获得性能,你可能不知道你到底在做什么.
答案是对的,但那不是问题吗?为什么我们认为问题揭幕者还没有意识到这一点?

2> Jon Skeet..:

如果您使用的是非常大的值类型(例如,Guid非常大),通过引用传递参数可能会稍微快一点.在其他情况下,当您通过引用传递而不是按值传递时可能会有更多复制等 - 例如,如果您有一个字节参数,那么一个字节明显少于指针在您使用的四个或八个字节通过引用传递它.

在实践中,你几乎不应该担心这一点.尽可能编写最易读的代码,这几乎总是意味着通过值而不是引用传递参数.我很少使用ByRef.

如果您想提高性能并认为ByRef会对您有所帮助,在提交之前仔细地(根据您的具体情况)对其进行基准测试.

编辑:我在评论中注意到另一个(以前接受的,现在删除的)答案,关于ByRef vs ByVal在价值类型方面的含义存在很多误解.我有一篇关于参数传递的文章,这篇文章多年来已经证明是流行的 - 它是在C#术语中,但同样的概念适用于VB.NET.



3> Kibbee..:

这取决于.如果要传递一个对象,它已经传递了一个指针.这就是为什么如果你传入一个ArrayList(例如)并且你的方法将一些东西添加到ArrayList,那么调用代码也有相同的对象进入它的ArrayList,传入,因为它是相同的ArrayList.它没有传递指针的唯一时间是将具有内部数据类型的变量(如int或double)传递给函数.此时,它会创建一个副本.但是,这些对象的数据大小非常小,在内存使用或执行速度方面几乎没有任何区别.



4> Scott Wisnie..:

如果传入引用类型,则ByRef较慢.

这是因为传入的是指向指针的指针.对对象上的字段的任何访问都需要取消引用额外的指针,这将需要几个额外的时钟周期才能完成.

如果传递值类型,那么如果结构有许多成员,则byref可能会更快,因为它只传递单个指针而不是复制堆栈上的值.在访问成员方面,byref会更慢,因为它需要进行额外的指针取消引用(sp-> pValueType-> member vs sp-> member).

在VB中大多数时候你不必担心这一点.

在.NET中,很少有具有大量成员的值类型.它们通常很小.在这种情况下,传入值类型与向过程传递多个参数没有什么不同.例如,如果您有按值传递Point对象的代码,则它的perf将与将X和Y值作为参数的方法相同.看到DoSomething(x为整数,y为整数)可能不会导致perf问题.事实上,你可能永远不会三思而后行.

如果您要定义自己的大值类型,那么您应该重新考虑将它们转换为引用类型.

唯一的另一个区别是执行代码所需的指针间接数量的增加.您很少需要在该级别进行优化.大多数情况下,您可以解决算法问题,或者您的性能瓶颈与IO相关,例如等待数据库或写入文件,在这种情况下,消除指针间接对您没有多大帮助.

因此,我不建议您应该专注于为您提供所需语义的内容,而不是专注于byter byval或byref更快.一般来说,除非你特别需要byref,否则最好使用byval.它使程序更容易理解.

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有