문제

에 VB.NET 있는,빠르게 사용하는 방법에 대한 인수 ByValByRef?

또한,소모에서 더 많은 자원을 runtime(RAM)?


을 통해 읽어 이 질문, 하지만 대답은 해당되지 않거나 특정 충분하다.

도움이 되었습니까?

해결책

Byval 및 Byref 주장은 요구 사항과 그들이 작동 방식에 대한 지식을 바탕으로 사용해야합니다. ~ 아니다 속도에.

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

Slough의 의견에 대한 응답으로 -

런타임에 더 많은 리소스를 소비하는 것은 무엇입니까?

매개 변수는 스택에 전달됩니다. 메모리 할당은 단순히 새로운 "프레임"또는 "할당 레코드"를 예약하기위한 포인터 증분이기 때문에 스택은 매우 빠릅니다. 대부분의 .NET 매개 변수는 기계 레지스터의 크기를 초과하지 않으므로 "스택"공간이 매개 변수를 전달하는 데 사용되는 경우 거의 없습니다. 실제로 기본 유형과 포인터는 모두 스택에 할당됩니다. .NET의 스택 크기는 1MB로 제한됩니다. 이렇게하면 매개 변수 통과로 자원이 소비되는지에 대한 아이디어를 제공해야합니다.

이 일련의 기사가 흥미로울 수 있습니다.

스택 할당을 통한 성능 향상 (.NET 메모리 관리 : 2 부)

어느 것이 더 빠르나요? Byval 또는 Byref.

측정의 맥락에 따라 정확하고 요정을 측정하는 것은 최상의 일이지만, 내가 쓴 벤치 마크는 다음과 같은 것을 생각해 냈습니다.

  • 참조 유형 - 통과 BYREF : 420ms
  • 참조 유형 - 통과 BYVAL : 382ms
  • 값 유형 - 통과 BYREF : 421ms
  • 값 유형 - 통과 BYVAL : 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
  • 참조 유형 - 통과 BYVAL : 349ms
  • 값 유형 - 통과 BYREF : 416ms
  • 값 유형 - 통과 BYVAL : 385ms

기준 유형 (문자열, 클래스)을 통과하면 시간이 조금 절약 될 수 있다고 결론을 내릴 수 있습니다. 또한 값 유형 (정수, 바이트) -Byval을 통과하면 시간을 절약 할 수 있다고 말할 수도 있습니다.

다시 한 번 웅대 한 사물의 계획에서는 시간이 무시할 수 있습니다. 더 중요한 것은 Byval과 Byref를 올바르게 사용하고 "무대 뒤에서"무슨 일이 일어나고 있는지 이해하는 것입니다. 루틴에서 구현 된 알고리즘은 프로그램의 런타임에 여러 번 더 많은 영향을 미칩니다.

다른 팁

매우 큰 값 유형을 사용하는 경우 (예 : Guid는 꽤 큽니다) 참조별로 매개 변수를 전달하는 것이 매우 빠를 수 있습니다. 다른 경우에는있을 수 있습니다 예를 들어, 바이트 매개 변수가있는 경우 값보다 참조별로 통과 할 때 복사 등을 복사하십시오. 예를 들어, 하나의 바이트는 참조로 전달하면 포인터가 취할 4 또는 8 바이트보다 분명히 적습니다.

실제로, 당신은 이것에 대해 거의 걱정하지 않아야합니다. 가장 많이 쓰십시오 읽을 수 있습니다 거의 항상 참조 대신 값별로 매개 변수를 전달하는 것을 의미합니다. 나는 Byref를 매우 드물게 사용합니다.

성능을 향상시키고 Byref가 도움이 될 것이라고 생각하면 제발 커밋하기 전에 신중하게 (정확한 상황에서) 벤치마킹하십시오.

편집 : 나는 다른 의견 (이전에 받아 들여진, 지금 삭제 된)에 주석에 주목합니다 (현재 삭제 된). Byref vs Byval이 가치 유형과 관련하여 무엇을 의미하는지에 대해 많은 오해가 있다고 대답합니다. 나는있다 매개 변수 통과에 관한 기사 수년에 걸쳐 인기있는 것으로 입증되었습니다. C# 용어에 있지만 VB.NET에는 동일한 개념이 적용됩니다.

때에 따라 다르지. 물체를 통과하는 경우 이미 포인터를 전달하고 있습니다. 그렇기 때문에 ArrayList (예 : 예를 들어)를 전달하고 메소드가 ArrayList에 Somings를 추가하면 호출 코드는 ArrayList와 동일한 개체를 갖습니다. 포인터를 통과하지 못하는 유일한 시간은 int 또는 Double과 같은 고유 데이터 유형으로 변수를 함수로 전달할 때입니다. 그 시점에서 사본을 만듭니다. 그러나 이러한 객체의 데이터 크기는 너무 작아서 메모리 사용 또는 실행 속도 측면에서 어느 쪽이든 차이를 만들지 않습니다.

참조 유형으로 통과하는 경우 Byref가 느려집니다.

전달되는 것이 포인터에 대한 포인터이기 때문입니다. 객체의 필드에 대한 액세스는 추가 포인터를 대리하는 데 도움이되므로 완료하는 데 몇 번의 추가 클록 사이클이 필요합니다.

값 유형을 통과하는 경우 구조물에 값을 복사하는 대신 단일 포인터 만 전달하기 때문에 구조에 부재가 많으면 Byref가 더 빠를 수 있습니다. 멤버에 액세스하는 관점에서, Byref는 추가 포인터 단축 (sp-> pvaluetype-> 멤버 대 Sp-> 멤버)을 수행해야하기 때문에 느리게됩니다.

VB에서 대부분의 시간은 이것에 대해 걱정할 필요가 없습니다.

.NET에서는 많은 회원이있는 가치 유형을 갖는 것은 드 rare니다. 그들은 보통 작습니다. 이 경우 값 유형을 통과하는 것은 여러 인수를 절차에 전달하는 것과 다르지 않습니다. 예를 들어, 점 객체에 값으로 전달 된 코드가 있다면 Perf는 x 및 y 값을 매개 변수로 취한 메소드와 동일합니다. 복용량 (x, 정수, y)을 보는 것은 아마도 성적 문제를 일으키지 않을 것입니다. 사실, 당신은 아마 그것에 대해 두 번 생각하지 않을 것입니다.

큰 가치 유형을 자신의 자아를 정의하는 경우, 아마도 참조 유형으로 전환해야 할 것입니다.

유일한 차이점은 코드를 실행하는 데 필요한 포인터 간접 수의 증가입니다. 해당 레벨에서 최적화 해야하는 경우는 드 rare니다. 대부분의 경우, 다룰 수있는 알고리즘 문제가 있거나 데이터베이스를 기다리거나 파일에 쓰기와 같은 Perf 병목 현상이 IO 관련이 있습니다.이 경우 포인터 간접을 제거하면 많은 도움이되지 않습니다.

따라서 Wheter Byval 또는 Byref에 초점을 맞추는 대신 더 빠릅니다. 필요한 의미를 제공하는 것에 실제로 집중해야합니다. 일반적으로 Byref가 필요하지 않으면 Byval을 사용하는 것이 좋습니다. 프로그램을 훨씬 쉽게 이해할 수 있습니다.

나는에 대해 많이 알지 못한의 내부.NET,에 대해 설명하겠습니다 무엇에 대해 알고 컴파일된 언어입니다.이 는 적용되지 않을 참조하 유형, 와 완벽히 차단되지 않을 수 있습에 대한 정확한 값 형식입니다.지 않으면 사이의 차이를 알고 가치 유형과 유형을 참조해서는 안 됩이 읽어 보시기 바랍니다.나는 가정 32-bit x86(32 비트 포인터).

  • 값을 전달하는 작은 32 비트로는 여전히 사용하는 32-bit 체에서 스택입니다.이것의 일부 개체 될 것"사용"이나"padding".통과 같은 값을 사용하지 않는 더 적은 메모리보다는 전달하는 32 비트 값이 있습니다.
  • 값을 전달하는 더 큰 것보다는 32 비트가 더 많이 사용됩 스택보다 공간에 포인터,아마 더 복사하는 시간입니다.
  • 면 이 값에 의해 전달,수신자 가져올 수 있는 객체에서 스택입니다.는 경우 객체 참조에 의해 전달되는,수신자가 먼저 가져올 객체의 주소를 스택에서 다음을 가져올 객체의 값을 다른 곳에서.의 값을 의미 하나 적게 가져오죠?만,실제로 가져올 수행해야 호출자에 의해-그러나 발신자도 이미를 가한 다른 이유에는 경우 인가 저장됩니다.
  • 물론 모든 변경 사항을 참조로 값이 저장되어야 합를 RAM 에는 반면,값을 매개 변수 삭제할 수 있습니다.
  • 그것의 더 나은 값으로 전달하는 것보다 참조 전달을 매개 변수를 복사로 지역 변수와 접촉하지 않습니다.

판결:

그것은 훨씬 더 중요한 것이 이해하 ByVal 및 ByRef 실제로 당신을 위해,그리고 사이의 차이를 이해의 가치와 기준 형태,이에 대해 생각하는 성능이다.수은 규칙 택하여 사용하는 방법은 더 많은 적합한 코드.

에 대한 큰 가치 유형(보다 더 많은 64 비트),참조로 전달하기가 없는 한 이용을 통하여 값(과 같은 간단한 코드를"그것은 단지 의미가",또는 인터페이스의 일관성).

을 위한 작은 가치 유형,전달 메커니즘하지 않는 많은 차이를 만들 수하의 성능,그리고 어쨌든 그것은 예측하기 어려운 방법은 빠를 것이기 때문에,객체 크기에 따라 다릅는 방법,발신자와 수신자가 사용하는 개체에도 캐시 고려 사항입니다.그냥 무엇이든 자신의 코드입니다.

ByVal 변수의 사본을 만듭니다 ByRef 포인터를 통과합니다. 그러므로 나는 그렇게 말할 것입니다 ByVal 시간이 걸리기 때문에 (복사하는 데 걸리기 때문에) 더 많은 메모리를 사용합니다.

내 호기심을 확인하는 다른 행동을 따라 개체 메모리 사용법

결과 보 demostrate 는 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