.NET简谈互操作(六:基础知识之提升平台调用性能)

互操作系列文章:

  1. .NET简谈互操作(一:开篇介绍)

  2. .NET简谈互操作(二:先睹为快)

  3. .NET简谈互操作(三:基础知识之DllImport特性)

  4. .NET简谈互操作(四:基础知识之Dispose非托管内存)

  5. .NET简谈互操作(五:基础知识之Dynamic平台调用)

  6. .NET简谈互操作(六:基础知识之提升平台调用性能)

  7. .NET简谈互操作(七:数据封送之介绍)

我们继续.NET互操作学习。本篇文章我们将来学习互操作基础知识中的最后一个知识点“提升平台调用的性能”;

在于非托管函数进行互操作的过程中,由于涉及的技术因数众多,因此程序的性能会受到这些因素的影响导致性能下降,本篇文章将来介绍在平台调用过程中提升性能的一些设计和编码方面的技巧;[王清培版权所有,转载请给出署名]

一:显示的制定要调用的非托管函数名称

我们在进行平台调用的时候,如果CLR无法在非托管DLL中找到与DllImport特性指定的函数名相同的非托管函数,那么CLR会尝试采用一些规则重新进行搜索。比如我们将sumA非托管函数的CharSet申明为CharSet.Ansi,那么CLR首先会通过根函数名(sum)进行搜索,如果在指定的非托管DLL中找到了此函数,就是用它。如果不能找到,就会使用带后缀A的函数(sumA)进行搜索。其实为什么会出现这种情况,原因来自于字符编码的不同,有的函数实现是采用Ansi方式,有的采用Unicode方式,这两种编码方式的不同最终导致数据在内存的存放也不同,所以在进行非托管调用的时候,我们需要注意;

非托管代码:

extern "C" _declspec(dllexport) int _stdcall addA(int x,int y)
{
 return x+y;
}

托管代码申明1:

[DllImport("Win32DLL.dll",EntryPoint = "add", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public static extern int add(int x, int y);

托管代码申明2:

[DllImport("Win32DLL.dll",EntryPoint = "addA", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall,ExactSpelling=true)]
public static extern int add(int x, int y);

上面两段托管代码申明有些细微的不同的,第一个托管代码是我们常见的申明方式,而第二个是我们少见的申明,两种不同的申明方式对CLR的平台调用来说是不一样的,相对而言的调用过程也有少许的不同,经测试第二种的申明能提升少许的性能;第二种的代码申明中出现了ExactSpelling=true(显式的指定要调用的非托管函数的名称),这段代码的意思是说,我们强制使用EntryPoint申明的方法入口点,不允许CLR帮我们去动态的调整函数的名称在去查找入口名称,这样能省掉了CLR的查找时间;

二:对数据封送处理进行优化

在托管代码与非托管代码之间传递参数时,无论是传入还是传出,都要经过封送拆收器的封送处理。由于封送过程可能会涉及数据类型的转换,以及在非托管内存与非托管内存之间来回复制数据,所以封送处理也是影响平台调用性能的瓶颈之一。

CLR在进行数据封送时,只有两种选择的方式:要么锁定数据、要么复制数据。在默认的情况下CLR会在封送过程中复制数据,假如我们需要将一个Unicode字符串作为Ansi传递到非托管代码中时,首先CLR会将字符串复制一份出来,然后将复制出来的字符串进行转换成Ansi,然后在将转换后的Ansi字符串的内存地址传递给非托管代码;由于复制数据操作可能很浪费时间,所以封送数据也是影响性能的瓶颈之一;

数据封送还有一种就是锁定内存的方式,意思就是说CLR可以通过直接将托管对象锁定在垃圾回收堆上,已防止托管对象在函数调用生命周期内被回收,一旦托管对象被锁定,就可以直接将指向托管对象的指针传递给非托管代码中,这样就避免了复制数据的操作,达到优化的目的;

但是不是所有的数据类型都能被锁定的,要想能被锁定,必须具备一些跟平台相关的约定,我们来看要满足那些条件的对象才能被CLR锁定;

1.必须是托管代码调用非托管代码,也就是本机代码;

2.托管数据类型必须是可直接复制到本机结构(blittable)中的数据类型,或者能够在满足某些条件下转换成本机结构数据类型;

3.传递的不是引用(ref,out)参数;

4.被调用代码和调用代码必须处于同一线程上下文或者线程单元中;

经过我们上面的总结,我们就可以发现,要想减少封送拆收器的数据复制操作,我们可以用本机结构类型进行传递,所谓本机结构类型就是在托管内存中和非托管内存中的表示形式是完全一样的。[王清培版权所有,转载请给出署名]

所以在准备开发平台调用程序时,我们尽量的考虑使用本机数据结构;如:System.Byte:无符号8位整型、System.SByte:有符号8位整型;

总结:由于这篇文章涉及到了数据封送的相关技术,很快我们结束了基础部分的学习,下面我们将进入学习互操作数据封送相关技术;

时间: 2024-09-20 08:44:02

.NET简谈互操作(六:基础知识之提升平台调用性能)的相关文章

.NET简谈互操作(五:基础知识之Dynamic平台调用)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.在上篇文章中我们学习了关于托管与非托管内存Dispose(释放)问题:下面我们继续学习基础知识中的Dyn

.NET简谈互操作(三:基础知识之DllImport特性)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之释放非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习,上一篇文章中我们介绍了托管代码怎么与非托管代码C++之间的互操作:要想在托管代码中成功的进行非托管调用,要注意的细

.NET简谈互操作(四:基础知识之Dispose非托管内存)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用)  .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.前一篇文章中我们学习了基础知识中的DllImport关键特性:我们继续学习基础知识中的内存释放相关技术

.NET简谈互操作(七:数据封送之介绍)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之Dispose非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习.互操作的基础知识已经差不多完了,当然一篇小小的文章很难全面的讲述互操作的方方面面,本人只是总结出关键的地

.NET简谈互操作(二:先睹为快)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之释放非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 我们继续.NET互操作学习,为了揭开互操作的神秘面纱,今天这篇文章我们就来先睹为快,让我们先来做个例子,基础的东西,我们陆续进行讲解:由于互操

.NET简谈互操作(一:开篇介绍)

互操作系列文章: .NET简谈互操作(一:开篇介绍) .NET简谈互操作(二:先睹为快) .NET简谈互操作(三:基础知识之DllImport特性) .NET简谈互操作(四:基础知识之释放非托管内存) .NET简谈互操作(五:基础知识之Dynamic平台调用) .NET简谈互操作(六:基础知识之提升平台调用性能) .NET简谈互操作(七:数据封送之介绍) 本人最近在学习非托管C++互操作的技术,有点小收获不敢私藏拿出来跟大家分享:作为.NET开发人员,我们有必要学习一些互操作方面的知识:尤其对一

Javascript浅谈之this_基础知识

介绍this在各种对面对象编程中起着非常重要的作用,主要用于指向调用的对象.不过在JavaScript中,this的表现存在很大差异,特别是不同执行上下文. 由前文我们知道this也是属于执行上下文中的一个属性,所有它命中注定和执行上下文脱不了干系. 复制代码 代码如下: activeExecutionContext = {VO: {...},this: thisValue}; 在Javascript中,this的取值取决于调用的模式.调用模式一共有四种:方法调用模式.函数调用模式.构造器调用模

《循序渐进Linux(第2版) 基础知识 服务器搭建 系统管理 性能调优 虚拟化与集群应用》——1.4 用虚拟机技术学习Linux

1.4 用虚拟机技术学习Linux 1.4.1 虚拟机技术 虚拟机(Virtual Machine)指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. 虚拟机会生成现有操作系统的全新虚拟镜像,它与真实系统具有完全一样的功能,进入虚拟机后,所有操作都在这个全新的独立虚拟系统里面进行,可以独立安装.运行软件,保存数据,拥有自己的独立桌面,这不会对真实的系统产生任何影响,而且能够在现有系统与虚拟机之间灵活切换. 1.4.2 使用虚拟机技术的好处 使用虚拟机技术的好处有以

【Python数据挖掘课程】六.Numpy、Pandas和Matplotlib包基础知识

        前面几篇文章采用的案例的方法进行介绍的,这篇文章主要介绍Python常用的扩展包,同时结合数据挖掘相关知识介绍该包具体的用法,主要介绍Numpy.Pandas和Matplotlib三个包.目录:        一.Python常用扩展包         二.Numpy科学计算包         三.Pandas数据分析包         四.Matplotlib绘图包         前文推荐:        [Python数据挖掘课程]一.安装Python及爬虫入门介绍