关于C#调用非托管动态库方式的性能疑问

  最近的项目中,因为一些原因,需要C#调用非托管(这里为C++)的动态库。网上喜闻乐见的方式是采用静态(DllImport)方式进行调用。偶然在园子里看到可以用动态(LoadLibrary,GetProcAddress,FreeLibrary)方式调用非托管动态库,于是就想着比较一下静态和动态方式的性能(主要想用运行时间来体现)。

  以下为源码:

  1.主程序源码:

 using System;
using System.Diagnostics;
using System.Text;
using System.Threading; namespace DllImportDemo
{
internal class Program
{ private static void Main()
{ const int callCount = ;
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
var watch = new Stopwatch();
watch.Start();
while (watch.ElapsedMilliseconds < )
{ }
watch.Stop();
watch.Restart();
Console.WriteLine("DllImportStatic will be called.");
for (var i = ; i < callCount; i++)
{
DllImportStatic();
}
watch.Stop();
Console.WriteLine("It costs {0}ms when DllImportStatic is called {1} times.",
watch.ElapsedMilliseconds, callCount); watch.Restart();
Console.WriteLine("DllImportDynamic will be called.");
for (var i = ; i < callCount; i++)
{
DllImportDynamic();
}
watch.Stop();
Console.WriteLine("It costs {0}ms when DllImportDynamic is called {1} times.",
watch.ElapsedMilliseconds, callCount);
Console.Read();
} private static void DllImportStatic()
{
IniHelper.ReadIniData("info", "v.productname", string.Empty, "./extends.properties");
} private static void DllImportDynamic()
{
ReadIniData("info", "v.productname", string.Empty, "./extends.properties");
} private delegate long GetPrivateProfileString(string section, string key,
string def, StringBuilder retVal, int size, string filePath); private static string ReadIniData(string section, string key, string noText, string iniFilePath)
{
var invoker = new DllInvoker("kernel32.dll"); var profileString = (GetPrivateProfileString)invoker.Invoke("GetPrivateProfileStringA",
typeof(GetPrivateProfileString)); var valueItem = new StringBuilder(); profileString(section, key, noText, valueItem, , iniFilePath); return valueItem.ToString();
}
} }

  2.动态调用托管动态库源码(部分代码参考网络)

 using System;
using System.Runtime.InteropServices; namespace DllImportDemo
{
class DllInvoker
{ [DllImport("kernel32.dll")]
private extern static IntPtr LoadLibrary(String path); [DllImport("kernel32.dll")]
private extern static IntPtr GetProcAddress(IntPtr lib, String funcName); [DllImport("kernel32.dll")]
private extern static bool FreeLibrary(IntPtr lib); private readonly IntPtr _hLib; public DllInvoker(string dllPath)
{
_hLib = LoadLibrary(dllPath);
} ~DllInvoker()
{
FreeLibrary(_hLib);
} /// <summary>
/// 将要执行的函数转换为委托
/// </summary>
/// <param name="apiName"></param>
/// <param name="type">委托类型</param>
/// <returns></returns>
public Delegate Invoke(string apiName, Type type)
{
var api = GetProcAddress(_hLib, apiName);
return Marshal.GetDelegateForFunctionPointer(api, type);
}
}
}

  3.静态调用动态库源码(部分代码参考网络)

 using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text; namespace DllImportDemo
{
public class IniHelper
{
#region API函数声明 /// <summary>
/// ini文件读取函数
/// </summary>
/// <param name="section">ini文件节点名称</param>
/// <param name="key">节点下面项的key值</param>
/// <param name="def">项key对应值的默认值,如果通过项key查找到结果,返回该结果;
/// 如果未找到,返回指定的默认值</param>
/// <param name="retVal">字符串缓冲区,即返回结果的存储区</param>
/// <param name="size">字符串缓冲区初始大小</param>
/// <param name="filePath">ini文件路径</param>
/// <returns>返回取得字符串缓冲区的长度</returns>
[DllImport("kernel32")]
private static extern long GetPrivateProfileString(string section, string key,
string def, StringBuilder retVal, int size, string filePath); #endregion #region 读Ini文件 public static string ReadIniData(string section, string key, string noText, string iniFilePath)
{
if (File.Exists(iniFilePath))
{
var temp = new StringBuilder(); GetPrivateProfileString(section, key, noText, temp, , iniFilePath); return temp.ToString();
}
return String.Empty;
} #endregion
}
}

  4.运行结果:

aaarticlea/png;base64,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CEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhLzABCWmAeAsMQ8AIQl5gEgLDEPAGGJeQAIS8wDQFhiHgDCEvMAEJaYB4CwxDwAhCXmASAsMQ8AYYl5AAhLzANAWGIeAMIS8wAQlpgHgLDEPACEJeYBICwxDwBhiXkACEvMA0BYYh4AwhqL+a2trd0u29vbYh4AjpixmN/d3f3kJz9533333Xfffffff/9nPvOZr371q48++uju7q6YB4AjpvOr+QcffPBLX/rSww8/fOzYsRMnTvhqHgCOpMn/Nj9K+m984xs/+clPXnrppVHG+2/zAHD0jGL++vXrt27d2v/Xdtvb27u7u8ePH9/PeDEPAEfPKObX1tZu37692bKzs/P+++/v7Ozs92xtbW1vb4t5ADgyRjF/69atUZAXbG9vi3kAOEpGMb+xsTEZ6vvR3ibmAeDIGMX8ZKLv7OyM/hwj5gHgyBjF/GSc54h5ADgyRjG/2kfvmL8MABwdPWK+AQCOmu6Y/83pVU3TNE3TgjUxr2mapmlhm5jXNE3TtLBNzGuapmla2CbmNU3TNC1s+385/XCShlteTwAAAABJRU5ErkJggg==" alt="" />

  疑问:

  从表面来看,读取ini文件的静态方式,只采用了一次[DllImport],动态调用时采用了两次[DllImport](FreeLibrary在析构函数中调用),按道理静态方式执行速度会快一些,但结果却相反,不知道是理解的问题还是其它什么原因?

[DllImport("kernel32")]
private static extern long GetPrivateProfileString(string section, string key,string def, StringBuilder retVal, int size, string filePath);

  

  

上一篇:SVN源代码的版本控制系统使用简介


下一篇:修改nignx报错Nginx [emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use)