在VB.NET,这是快要用于方法的论点, ByValByRef?

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


我读过 这个问题, 但答案是不适用或不够具体。

有帮助吗?

解决方案

果你正在调试和ByRef参数应用于基于要求和知识的他们是如何工作的 速度。

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

在应对一种评论,由斯劳

这要消耗更多的资源,在运行时?

参数是通过对叠。这堆是非常快,因为它的存分配是一个简单的指针增订一个新的"框架"或"分配记录。" 大多数。净参数不超过机器登记册所以很少,如果任何"堆"空间是用来通过的参数。事实上基本类型,并指针,都分配在栈。堆大小。净是限于1兆。这应该给你的想法多少资源消耗的参数通过。

你可以找到这一系列文章,有趣:

改善性能的通过堆分配(.净存管理:第2部分)

这是更快吗?果你正在调试或ByRef.

这是很难在最好的要准确的测量和童话-根据上下文的测量,但是一个基准我写的呼吁的一种方法100万次了以下:

  • 引用类型过ByRef:420ms
  • 参照类型的传果你正在调试:382ms
  • 值的类型-通过ByRef:421ms
  • 值型通果你正在调试:416ms
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:389ms
  • 参照类型的传果你正在调试:349ms
  • 值的类型-通过ByRef:416ms
  • 值型通果你正在调试:385ms

一个可能的结论是,通过引用类型(strings,类)果你正在调试将节省一些时间。你也可以说,通过值类型(integer,byte)-果你正在调试将节省一些时间。

再一次的时间是可以忽略的事情。什么是更重要的是使用果你正在调试和ByRef正确和理解这是怎么回事"幕后"。 算法实现在你的程序将大多数肯定会影响运行程序的许多倍。

其他提示

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

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

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

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

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

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

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

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

大部分时间在VB中你不必担心这个。

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

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

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

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

虽然我不知道很多关于内部。净,我将讨论是什么我知道关于汇编的语言。此 不适用的基准类型, 可能不完全准确价值的类型。如果你不知道之间的差值的类型和基准类型,你不应该读这个.我会承担的32位x86(32-bit指针).

  • 传递的价值小于32-位仍然使用一个32位上的对象堆。这部分的目的将"未用"或"填充".通过这种价值观不使用较少的内存比穿的32位的价值观。
  • 传递的价值大于32-位将使用更多的堆空间,比指针,并且可能更多的复制时间。
  • 如果一个目的是通过价值,被叫方可以获取的对象,从栈。如果一个目的是通过参考,被须首先获取的对象的地址从栈,然后获取对象的价值,从其他地方。通过价值意味着一个小拿,对吗?嗯,实际上获取需要做的叫-但是呼叫者可能已经不得不取用不同的原因,在这种情况下,获取失。
  • 显然所做的任何更改的参考价值,必须保存的背撞,而一个由价值的参数可以被废弃。
  • 最好通过价值,而不是通过仅供参考,以复制参数进入一个当地的可变和不再触摸它。

该判决:

它更重要的是要了解什么果你正在调试和ByRef实际上为你做点,并理解之间的差值和基准类型,而不考虑性能。第一条规则是 使用哪种方法是较为适当你的代码.

大价值的类型(超过64位),通过参考,除非有一个优势,通过价值(例如简单的代码,"它只是使得有意义",或口的一致性).

对于价值较小类型的传递机制并没有多大差异性,且无论如何,很难预测哪些方法将更快,因为它取决于物体的大小,怎么呼叫者和被叫方使用的对象,甚至缓方面的考虑。只是做什么的意义。

ByVal 创建变量的副本,而 ByRef 传递指针。因此,我会说 ByVal 较慢(由于复制所需的时间)并使用更多内存。

我的好奇心是根据对象和记忆用法来检查不同的行为

结果似乎证明ByVal总是赢,资源依赖于收集内存或更少(仅限4.5.1)

Public Structure rStruct
    Public v1 As Integer
    Public v2 As String
End Structure

Public Class tClass
    Public v1 As Integer
    Public v2 As String
End Class



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

Public Sub Method5(ByVal st As rStruct)
    Dim x As rStruct = st
End Sub

Public Sub Method6(ByRef st As rStruct)
    Dim x As rStruct = st
End Sub


Public Sub Method7(ByVal cs As tClass)
    Dim x As tClass = cs
End Sub

Public Sub Method8(ByRef cs As tClass)
    Dim x As tClass = cs
End Sub
Sub DoTest()

    Dim s As String = "Hello World!"
    Dim cs As New tClass
    cs.v1 = 1
    cs.v2 = s
    Dim rt As New rStruct
    rt.v1 = 1
    rt.v2 = s
    Dim k As Integer = 5




    ListBox1.Items.Add("BEGIN")

    Dim t As New Stopwatch
    Dim gt As New Stopwatch

    If CheckBox1.Checked Then
        ListBox1.Items.Add("Using Garbage Collection")
        System.Runtime.GCSettings.LargeObjectHeapCompactionMode = System.Runtime.GCLargeObjectHeapCompactionMode.CompactOnce
        GC.Collect()
        GC.WaitForPendingFinalizers()
        GC.Collect()
        GC.GetTotalMemory(False)
    End If

    Dim d As Double = GC.GetTotalMemory(False)

    ListBox1.Items.Add("Free Memory:   " & d)

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

    ListBox1.Items.Add("Reference Type - ByRef " & t.ElapsedMilliseconds)

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

    ListBox1.Items.Add("Reference Type - ByVal " & t.ElapsedMilliseconds)

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

    ListBox1.Items.Add("Value Type - ByRef " & t.ElapsedMilliseconds)

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

    ListBox1.Items.Add("Value Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method5(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method6(rt)
    Next
    t.Stop()

    ListBox1.Items.Add("Structure Type - ByRef " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method7(cs)
    Next
    t.Stop()

    ListBox1.Items.Add("Class Type - ByVal " & t.ElapsedMilliseconds)

    t.Reset()
    t.Start()

    For i As Integer = 0 To 100000000
        Method8(cs)
    Next
    t.Stop()
    gt.Stop()

    ListBox1.Items.Add("Class Type - ByRef " & t.ElapsedMilliseconds)
    ListBox1.Items.Add("Total time " & gt.ElapsedMilliseconds)
    d = GC.GetTotalMemory(True) - d
    ListBox1.Items.Add("Total Memory Heap consuming (bytes)" & d)


    ListBox1.Items.Add("END")

End Sub


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click


    DoTest()

End Sub
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top