提高平台调用性能
提高平台调用性能的一些方式
- 显式地指定非托管函数的名称
为了提升性能,最佳的做法是一旦确定了要调用的函数,最好将ExactSpelling
字段设置为true以阻止CLR通过修改入口点名称来搜索函数。
- 尽量使用Blittable类型
CLR在数据封送时,有两种选择,一是锁定(pin)对象,阻止托管对象在函数调用期间被移动或者回收。二是对数据进行复制。复制的操作比较费时,是影响平台调用性能的因素之一。
锁定托管对象需要满足的条件:
- 必须是托管代码调用本机代码。
- 托管数据类型必须是Blittable类型或者能转变成Blittable类型的数据类型。
- 传递的不是引用参数(ref或out)。
- 被调代码和调用代码必须在同一线程上下文或者线程单元。
- 尽可能减少数据封送次数
如果可能的话,尽量不要逐次对非托管函数进行平台调用。如果平台调用结果只是中间结果,则可以将所有的计算过程放到非托管函数中。
- 尽量避免字符串编码转换
字符集的转换必然会牺牲性能,复制字符串到非托管内存时,也是会耗费时间的,从而带来性能损失。
关于Blittable类型
Blittable类型是指对于托管代码和非托管代码而言,其在内存中的表示形式完全一样的数据类型。
Blittable数据类型:
|数据类型|描述|
|-|-|
|System.Byte
|无符号8位整型|
|System.SByte
|有符号8位整型|
|System.Int16
|…|
|System.UInt16
|…|
|System.Int32
|…|
|System.UInt32
|…|
|System.Int64
|…|
|System.UInt64
|…|
|System.Single
|…|
|System.Double
|…|
|System.IntPtr
|平台相关的有符号指针类型|
|System.UIntPtr
|平台相关的无符号指针类型|
Non-Blittable数据类型:
|数据类型|描述|
|-|-|
|System.Array
|转换为C风格的数组或者SAFEARRAY|
|System.Boolean
|转换为1字节、2字节或4字节的整数值|
|System.Char
|转换为Unicode或者ANSI|
|System.Class
|转换成类接口|
|System.Object
|转换成变量或者接口|
|System.Mdarray
|转换为C风格的数组或者SAFEARRAY|
|System.String
|转换成’/0’结束的C风格字符串或者BSTR|
|System.ValueType
|转换成固定内存布局的结构体|
|System.Szarray
|转换为C风格的数组或者SAFEARRAY|
其他Blittable数据类型:
|数据类型|描述|
|-|-|
|Blittable[]
|元素是Blittable类型的一维数组|
|blittable struct|成员数据类型都是Blittable类型的格式化值类型|
其他的可变成Blittable类型的数据类型示例:
|数据类型|描述|
|-|-|
|char(Unicode)|(将CharSet显式指定为Unicode)|
|MarshalAs(UnmanagedType.LPWSTR) char
|或者单独为char类型加上MashalAs特性|
|…|…|
(END)