'Dynamic binding'에 해당되는 글 1건

  1. 2010.01.19 .NET Dynamic Binding (1)
VB.NET2010.01.19 18:55
얼마전 유명한 IT 컨설턴트이신 안재우 수석 님의 블로그(http://blog.naver.com/saltynut/120097740266)에서 VB의 성능이 떨어진다고 하시는것같은 느낌을 받아서 댓글을 달았습니다만 더 자세히 알아보니 다른부분이 좀 있긴 했습니다.

Dynamic 과 LateBinding 이 다른 레벨이라고 안수석님이 설명하셨듯이 다른 레벨이 맞습니다. LateBinding 이 Dynamic 에 포함된 부분이죠.

그러면, 제가 의아해 했던 부분인 DataType을 Object 형으로 선언 했을때와 하지 않았을때의 결과는 완전히 다르게 나타납니다.

Sub Main()

    Dim factory As PersonFactory = New PersonFactory()
    Dim person As Object = factory.Create("moonhyuk")
    person.Greeting()

End Sub


'------------------- or ----------------------

Sub Main()

    Dim factory As PersonFactory = New PersonFactory()
    Dim person = factory.Create("moonhyuk")
    person.Greeting()

End Sub

위처럼 두가지 방법으로 다이나믹 코드를 작성 할수가 있는데요,  DataType을 Object로 선언을 한 부분은 컴파일 후 리팩터를 통해서 보면 다음처럼 변환이 되어 있습니다.

NewLateBinding.LateCall(RuntimeHelpers.GetObjectValue(factory.Create("moonhyuk")), Nothing, _
"Gretting", New Object(0-1){}, Nothing, Nothing, Nothing, True)


두번째, DataType를 선언 하지 않은 전통적 방법의 Dynamic 선언은

factory.Create("moonhyuk").Gretting

처럼 깔끔하게 바뀌게 됩니다.


이에 대해 VB-Insiders 에 문의 한 결과 VB.NET Spec lead 인 Lucian Wischik 에게 다음과 같은 답변이 왔습니다.

Sub f(Byval p as Person)
    p.Greeting()
End Sub
이 경우는 Greeting 메서드에 정적 바인딩이 되고, 컴파일러가 정확히 Greeting 메서드를 알고 있기 때문에 Early Binding이 되어 버립니다.
이말은 컴파일시에 바인딩이 되므로, Dynamic 이라 하기가 어렵다는것이죠. ㅡㅡ;


그러면, 두번째 경우인

Sub f(Byval p as Object)
    p.Greeting()
End Sub

이 경우가 다이나믹 바인딩이 되는것인데, 이때 System.Dynamic.IDynamicObjectProvider (다른말로 DLR 객체) 가 Greeting 이라는 메서드를 Invoke 합니다. 메서드 호출에 실패하면 COM 리플렉션을 통해 p 를 COM 이라고 생각하고 또다시 찾습니다. 그래도 실패하면 System.Reflection 의 look up 을 통해 Greeting 이라는 메서드를 찾습니다.

이 과정이 Microsoft.VisualBasic.dll의 NewLatebinding.LateCall 에 의해 처리가 됩니다.

Late Binding 또는 Dynamic Binding 을 할때 DLR call-site 인스턴스를 생성하게 되고, 다시 호출할때는 call-site를 참조를 합니다만, 아쉽게도 C#의 경우는 call-site cache 영역이 있지만, VB.NET 에는 cache 영역이 없습니다. ㅡㅡ;
이 부분 때문에 속도 차이가 이렇게 많이 나는 것 입니다. 이 부분은 인정 하지 않을수가 없습니다.

Late Binding 혹은 Dynamic Binding 은 성능에 우선을 두는게 아니라 유연함과 접근성에 중점을 두는것인데, 성능 비교를 한다는것 자체가 아이러니 합니다만, 단지 좋아하는 VB 가 성능이 나쁜 언어이고, 뒤쳐지는 언어 라는 느낌을 받아서 몇가지 테스트와 여러군데 자문을 구해보았습니다.

사실 몇천, 몇만번 이상의 반복적인 수행을 하는 코드에 다이나믹으로 처리 한다는것 자체가 이상하긴 하지만, 어쩔수 없이 써야 할 경우는 정성태 MVP 님의 C# 4.0 - dynamic 키워드 에서 사용하신 LCG 를 통한 성능 향상 방법도 있으니 참조하시면 좋겠네요.

결론을 짓자면, VB는 C# 보다 Dynamic Binding 이 느리다! 입니다.

Posted by dotnetpower

댓글을 달아 주세요

  1. neominky

    둘다 리플렉션에 기반한 방법 입니다. LateCall 은 범용적으로 쓸 수 있도록 만들어져 있다보니 검사하고 Lookup 하는 과정에서 많은 성능 저하가 발생합니다. dynamic은 이문제를 해결하려고 컴파일러가 LateCall의 최적화 코드를 마구 삽입 한것에 불과 합니다. LateCall을 좀더 좋게 따라하기 위해 나온것이 비슷하거나 느리면 안되겠죠. VB가 캐쉬를 두지 않는 것은 좀 의아하긴 합니다만(특수한 상황 문제일수도, C#도 같은 조건으로 프로시져를 분리해 봐야할듯) 제가 볼땐 전혀 다른 레벨이다 라고 보기보단 수평적으로 성능을 개선했다 정도로만 보입니다. LateCall 한개(?)를 따라하기 위해 매우 많은 사용자 코드를 조작하는데, 이러한 방법은 VB와 C의 컨샙이 서로 뒤바뀐것 같습니다. C#의 장점이 Reflector로 봤을때 사용자 코드와 거의 같은 내용으로 나오는 것이었는데 말이죠.

    2010.11.18 10:53 [ ADDR : EDIT/ DEL : REPLY ]