首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么.NET会成为测试测量的主流技术

背景—.NET的优势:

微软董事长兼首席软件设计师比尔盖茨曾说:“.NET 是指连接信息、人群、系统和设备的软件。”.NET迅速发展至今,其开源的策略,易用的开发机制,受到全球开发者的欢迎。越来越好的印证了盖茨这句话,也因此.NET技术从应用较多的web应用开发,逐步被应用到工业开发领域。.NET 是一个免费,跨平台,开源的开发平台,可用于几乎任何的应用开发。基于.NET, 你可以使用多种编程语言,编译器以及类库来创建网络,移动,桌面,游戏和物联网应用。

在开源社区中,全世界已经有超过25000个开发者和1700家公司贡献基于.NET平台的。在测试测量领域,.NET已经成为了主流技术,LabVIEW最新的版本LabVIEW NXG也是基于.NET开发的。同时简仪也加入了这其中,为全世界的测控工程师提供开源免费的软件技术,简仪用C#语言开发的锐视开发软件日趋完善,面向对象的.NET硬件驱动已经可以支持不同仪器厂商的模块仪器,完全打破了国外仪器厂商封闭不通用的局面。为了更好的实现软硬件无缝结合,简仪会持续开展一些列基于多语言,跨平台下.NET开发测控类应用的效率实验。

C#/C++/Python/LabVIEW四种语言是目前在测试测量界最通用的编程语言。本篇文章旨在测评C#/C++/Python/LabVIEW四种语言在调用.NET驱动下的效率和对.NET的支持情况。因为我们身处测试测量行业,而测试测量行业中最常用的就是对于大量数组的传输,因此我们采用对C#/C++/Python/LabVIEW调用.NET以数组为参数的方法的性能做为初步测试。

测试结论:

简仪科技委托聚星仪器工程师对C#/C++/Python/LabVIEW调用.NET以数组为参数的方法的性能做了初步测试,测试结论为:四种语言在.NET方法内部所消耗的时间差异不大。LabVIEW在调用方法时,尤其对于二维数组方法的调用,所消耗的时间非常长,效率非常低。

LabVIEW在测试测量的开发软件中地位无可厚非,但在调用.NET数组的效率上与其他面向对象的语言差距如此明显,让人百思不得其解。我们非常期望未来可以将这一问题解决。在目前阶段,推荐大家使用C#软件以解决此问题。

测试结果呈现:

工程师对C#/C++/Python/LabVIEW调用.NET以数组为参数的方法的性能做了测试,以下是各个语言调用测试类的各个方法的耗时(测试次数100次)

注:时间单位是ms

Inner/Call分别指.NET方法内部(内部取随机数并赋值给数组的每个元素)消耗的时间和调用.NET方法(除去inner)消耗的时间

每种形态的方法,内部都是对输入的指定大小数组的每个元素生成一个随机数(选随机数是为了排除编译器优化影响测试结果)

ref 2D:方法输入的数组参数是ref double[,]

ref 1D:方法输入的数组参数是ref double[]

2D:方法输入的数组参数是double[,]

1D:方法输入的数组参数是double[]

具体测试方法请见附录链接。

附录:测试方法

向上滑动阅览

测试类说明

C#中的DAQTest类(代码见下文)提供一个属性ChannelCount,四个GetData方法重载形式如下:

public double GetData(ref double[,] buf, int sampleCount)

public double GetData(double[,] buf, int sampleCount)

public double GetData(ref double[] buf, int sampleCount)

public double GetData(double[] buf, int sampleCount)

public unsafe double GetData(IntPtr buf, int sampleCount)

该方法的主要逻辑是:内部生成sampleCount*ChannelCount点随机数给输入的数组,并返回函数内部运行的时间(ms)。

Labview调用情况

01LV调用public double GetData(ref double[,] buf, int sampleCount)

总数据量为 4 x 1M的double数据,循环测试100次,实测函数内部执行的时间为91~147ms,而每次调用该方法的时间为1240~1352ms(已除去内部执行的时间)

02LV调用public double GetData(double[,] buf, int sampleCount)

总数据量为 4 x 1M的double数据,循环测试100次,实测函数内部执行的时间为92~108ms,而每次调用该方法的时间大约为1260~1320ms(已除去内部执行的时间)

03LV调用public double GetData(ref double[] buf, int sampleCount)

总数据量为 4 x 1M的double数据,循环测试100次,实测函数内部执行的时间为73~81ms,而每次调用该方法的时间大约为40~50ms(已除去内部执行的时间)

04LV调用public double GetData(double[] buf, int sampleCount)

总数据量为 4 x 1M的double数据,循环测试100次,实测函数内部执行的时间为74~86ms,而每次调用该方法的时间大约为44~57ms(已除去内部执行的时间)

05LV调用public unsafe double GetData(IntPtr buf, int sampleCount)

总数据量为 4 x 1M的double数据,循环测试100次,实测函数内部执行的时间为84~116ms,而每次调用该方法的时间大约为0~5ms(已除去内部执行的时间)

注:其中IntPtr作为输入参数在Laview中是通过图中的五步实现:

执行过程中,每调用一次GetData方法,数组中的值就会更新一次,说明这种方法是可行的,并且调用的效率与C#和C++中的效率已经非常接近了。

图中①是用lv的数组初始化函数创建一个二维数组;②是通过c++的函数获取①中创建的二维数组的地址;③是用②中获取到的地址创建一个IntPtr对象(相当于C#中的执行,这里并不会创建数组内存,只是将数组内存映射为IntPtr);④是调用C#的方法,该方法内部与其他形态的方法一样,只是在赋值时使用的是unsafe的指针进行;⑤处输出的数组中有随机数。

C#数组读取类的代码

public classDAQTest

{

publicDAQTest()

{

ChannelCount = 1;

}

public intChannelCount

{

get;set;

}

public doubleGetData(ref double[,] buf,intsampleCount)

{

doubleelapsedTime = 0;

varst =DateTime.Now;

varrd =newRandom();

for(intc = 0; c

{

for(inti = 0; i

{

buf[i, c] = rd.NextDouble();

}

}

varend =DateTime.Now;

elapsedTime = (end - st).TotalMilliseconds;

returnelapsedTime;

}

public doubleGetData(double[,] buf,intsampleCount)

{

doubleelapsedTime = 0;

varst =DateTime.Now;

varrd =newRandom();

for(intc = 0; c

{

for(inti = 0; i

{

buf[i, c] = rd.NextDouble();

}

}

varend =DateTime.Now;

elapsedTime = (end - st).TotalMilliseconds;

returnelapsedTime;

}

public doubleGetData(ref double[] buf,intsampleCount)

{

doubleelapsedTime = 0;

varst =DateTime.Now;

varrd =newRandom();

for(intc = 0; c

{

for(inti = 0; i

{

buf[i + c * sampleCount] = rd.NextDouble();

}

}

varend =DateTime.Now;

elapsedTime = (end - st).TotalMilliseconds;

returnelapsedTime;

}

public doubleGetData(double[] buf,intsampleCount)

{

doubleelapsedTime = 0;

varst =DateTime.Now;

varrd =newRandom();

for(intc = 0; c

{

for(inti = 0; i

{

buf[i + c * sampleCount] = rd.NextDouble();

}

}

varend =DateTime.Now;

elapsedTime = (end - st).TotalMilliseconds;

returnelapsedTime;

}

public unsafe doubleGetData(IntPtrbuf,intsampleCount)

{

doubleelapsedTime = 0;

varst =DateTime.Now;

varrd =newRandom();

for(intc = 0; c

{

for(inti = 0; i

{

*((double*)buf + i + c * sampleCount) = rd.NextDouble();

}

}

varend =DateTime.Now;

elapsedTime = (end - st).TotalMilliseconds;

returnelapsedTime;

}

}

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180712G15LBL00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券