在C++中反射调用.NET的方法(三)

2020-01-06 16:54:54于丽

性能测试

C++/CLI 反射性能测试

为了测试 C++/CLI 反射调用两种方案(直接反射调用,委托方法调用)的效率,我们循环1000次测试,下面是测试代码:


NetLibProxy::UserProxy^ proxy = gcnew NetLibProxy::UserProxy("..NetLibbinDebugNetLib.dll");
std::list<CppUserInfo> list = proxy->GetUsers("张");
 System::Console::WriteLine("C++ Get List data From .NET function,OK.");
 System::Diagnostics::Stopwatch^ sw = gcnew System::Diagnostics::Stopwatch;
 sw->Start();
 for (int i = 0; i<1000; i++)
 proxy->SaveUsers(list);
 sw->Stop();
 System::Console::WriteLine("1,1000 loop,C++ Post List data To .NET function,OK.use time(ms):{0}",sw->ElapsedMilliseconds);
 sw->Restart();
 for(int i=0;i<1000;i++)
 proxy->SaveUsers2(list);
 sw->Stop();
 System::Console::WriteLine("2,1000 loop,C++ Post List data To .NET function,OK..use time(ms):{0}", sw->ElapsedMilliseconds);

不调试,直接执行:


C++ Get List data From .NET function,OK.
1,1000 loop,C++ Post List data To .NET function,OK.use time(ms):65
2,1000 loop,C++ Post List data To .NET function,OK..use time(ms):48

可见,虽然在.NET程序端,我们使用了弱类型的泛型集合,综合起来还是反射+委托方法执行,效率要高。

所以如果你能够适当对要调用的.NET方法进行封装,那么可采用使用弱类型集合传输数据的方案,否则,就在C++/CLI端多写2行代码,使用强类型传输数据的方案。

与.NET直接调用和反射的性能比较

在本篇的方案中,都是C++反射来调用.NET方法的,如果都是在.NET应用程序中直接调用或者反射.NET方法,性能差距有多少呢?

我们模拟文中 C++/CLI的UserProxy,写一个.NET中的 UserProxy:


struct UserStruct
 {
  public int ID;
  public string Name;
  public DateTime Birthday;
 }
 class UserProxy
 {
  User user;
  public UserProxy()
  {
   user = new User();
  }
  public List<UserStruct> GetUsers(string likeName)
  {
   List<UserStruct> result = new List<NetApp.UserStruct>();
   var list = user.GetUsers(likeName);
   foreach (var item in list)
   {
    UserStruct us;
    us.ID = item.ID;
    us.Name = item.Name;
    us.Birthday = item.Birthday;
    result.Add(us);
   }
   return result;
  }
  public bool SaveUsers(IList<UserStruct> users)
  {
   List<IUserInfo> list = new List<IUserInfo>();
   IUserInfo userObj = user.CreateUserObject();
   foreach (var item in users)
   {
    IUserInfo currUser = (IUserInfo)((ICloneable)userObj).Clone();
    currUser.ID = item.ID;
    currUser.Name = item.Name;
    currUser.Birthday = item.Birthday;
    list.Add(currUser);
   }
   bool result = user.SaveUsers(list);
   return result;
  }

  Object CreateUserObject()
  {
   MethodInfo method = user.GetType().GetMethod("CreateUserObject", BindingFlags.Public | BindingFlags.Instance);
   Func<Object> fun = (Func<Object>)Delegate.CreateDelegate(typeof( Func<Object>), user, method);
   return fun();
  }
  //反射+委托
  public bool SaveUsers2(IList<UserStruct> users)
  {
   MethodInfo method = user.GetType().GetMethod("SaveUsers2", BindingFlags.Public | BindingFlags.Instance);
   Func<System.Collections.Generic.IEnumerable<Object>, bool> fun2 = (Func<System.Collections.Generic.IEnumerable<Object>, bool>)Delegate.CreateDelegate(typeof( System.Func<System.Collections.Generic.IEnumerable<Object>, bool>),
    user, method);
   List<IUserInfo> list = new List<IUserInfo>();
   object userObj = CreateUserObject();
   foreach (var item in users)
   {
    IUserInfo currUser = (IUserInfo)((ICloneable)userObj).Clone();
    currUser.ID = item.ID;
    currUser.Name = item.Name;
    currUser.Birthday = item.Birthday;
    list.Add(currUser);
   }
   bool result = fun2(list);
   return result;
  }
}
.Net UserProxy