사용자가 VB에서 작성된 부모 응용 프로그램에서 자신의 코드 (C# 또는 VB)를 실행할 수 있도록 AppDomain 샌드 박스를 만들었습니다. 필자는 필수 코드를 추출하여 두 개의 동일한 응용 프로그램을 만들었습니다. 하나는 VB에서 C#으로 된 응용 프로그램입니다.VB보다 AppDomain의 함수를 호출 할 때 C#이 훨씬 빠릅니다.
나는 C# 버전이 적어도 60 배 더 빠르게 실행된다는 사실에 놀랐다.
StackOverflow 또는 Google에서이 동작에 대한 참조를 찾을 수 없습니다. VB에서 Invoke
호출을 serialize하는 방식에 큰 비 효율성이 있습니까? (생성자 + 실행) 다음
Imports System.Reflection
Namespace UserCode
Namespace Runtime
Public Class Execute
Inherits MarshalByRefObject
Private _MethodInfo As MethodInfo
Sub New()
_MethodInfo = Nothing
End Sub
Public Sub SetAssembly(assemblyName As String, functionName As String)
_MethodInfo = Nothing
If assemblyName <> "" Then
Dim assembly As Assembly = AppDomain.CurrentDomain.Load(assemblyName)
Dim type As Type = assembly.GetType("CompiledUserCode")
_MethodInfo = type.GetMethod(functionName, BindingFlags.Public Or BindingFlags.Static)
End If
End Sub
Public Function ExecuteFunction(args() As Object) As Object
Return _MethodInfo.Invoke(Nothing, args)
End Function
End Class
End Namespace
End Namespace
는 해당 C 번호 여기
using System;
using System.Reflection;
namespace UserCode
{
public class Execute:MarshalByRefObject
{
private MethodInfo _MethodInfo;
public Execute()
{
_MethodInfo = null;
}
public void SetAssembly(string assemblyName ,string functionName)
{
_MethodInfo = null;
if(assemblyName != "")
{
var assembly = AppDomain.CurrentDomain.Load(assemblyName);
var type = assembly.GetType("CompiledUserCode");
_MethodInfo = type.GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
}
}
public object ExecuteFunction(object[] args)
{
return _MethodInfo.Invoke(this, args);
}
}
}
인 VB IL은 :
.class public auto ansi UserCode.Runtime.Execute
extends [mscorlib]System.MarshalByRefObject
{
// Fields
.field private class [mscorlib]System.Reflection.MethodInfo _MethodInfo
// Methods
.method public specialname rtspecialname
instance void .ctor() cil managed
{
// Method begins at RVA 0x21c0
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.MarshalByRefObject::.ctor()
IL_0006: ldarg.0
IL_0007: ldnull
IL_0008: stfld class [mscorlib]System.Reflection.MethodInfo UserCode.Runtime.Execute::_MethodInfo
IL_000d: ret
} // end of method Execute::.ctor
.method public
instance object ExecuteFunction (
object[] args
) cil managed
{
// Method begins at RVA 0x221c
// Code size 14 (0xe)
.maxstack 3
.locals init (
[0] object ExecuteFunction
)
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Reflection.MethodInfo UserCode.Runtime.Execute::_MethodInfo
IL_0006: ldnull
IL_0007: ldarg.1
IL_0008: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, object[])
IL_000d: ret
} // end of method Execute::ExecuteFunction
여기
는 종류가 실행중인 VB 코드
다음은 C# IL입니다.
내가 볼 수.class public auto ansi beforefieldinit UserCode.Execute
extends [mscorlib]System.MarshalByRefObject
{
// Fields
.field private class [mscorlib]System.Reflection.MethodInfo _MethodInfo
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Method begins at RVA 0x275c
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.MarshalByRefObject::.ctor()
IL_0006: ldarg.0
IL_0007: ldnull
IL_0008: stfld class [mscorlib]System.Reflection.MethodInfo UserCode.Execute::_MethodInfo
IL_000d: ret
} // end of method Execute::.ctor
.method public hidebysig
instance object ExecuteFunction (
object[] args
) cil managed
{
// Method begins at RVA 0x27b4
// Code size 14 (0xe)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Reflection.MethodInfo UserCode.Execute::_MethodInfo
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: callvirt instance object [mscorlib]System.Reflection.MethodBase::Invoke(object, object[])
IL_000d: ret
} // end of method Execute::ExecuteFunction
유일한 큰 차이는 다음과 같습니다 현재
.maxstack 3
.locals init (
[0] object ExecuteFunction
)
내 유일한 옵션은 샌드 박스 코드를 포함하는 별도의 C# 어셈블리를 생성하는 것입니다 C#을 속도를 활용하고자하는 경우. 60 번은 실제로 과소 평가입니다. 인수로
object[] objects = new object[] { 1.0, 1.0, 1.0 };
및 object[0]
변화하는 것은 어떤 최적화 (100000 루프)를 방지하기 위해 : 그것은으로 ExecuteFunction
함수를 호출하여 간단하게 측정한다. 실제로 샌드 박스에서 실행됩니다
의 코드는 매우 간단합니다 : 재 측정 속도의 차이에
public static double StressFactor(double useStress, double stress, double p)
{
return useStress*stress+p;
}
가까이에 41 배 빠른 C#에서입니다.
VB 및 C#은 여러 가지면에서 거의 동일하지만 완전히 동일하지는 않습니다. 중요한 성능 불일치를 예상 할 이유가 없습니다. 나는 당신의 "동일한"응용 프로그램이 당신이 기대하는만큼 동일하지 않을 것이라고 생각합니다. –
그 게시물에 코드가 포함되어 있지 않다는 사실에 놀랐습니다. 이 시점에서 당신은 당신이 잘못한 것에 대해 추측을 표현할 수 있습니다 ... –
귀하의 진술이 정확하다고하더라도, 여기에 몇 가지 코드를 넣어 증명할 필요가 있으며, _60 배 빠른 곳을 알려주십시오. 다른 사람들이 그것에 대해 토론 할 수 있도록하십시오. –