WinRT开发系列之编程语言:功能和效率
2013-02-19 12:11
169 查看
WinRT开发有着多种选择性,就编程语言这一点就表现的很突出;这里就这一点深入展开,探讨在WinRT开发之初如何依据各个编程语言的特性、功能和效率来对产品的技术方向做出选择。
这里我选择运行计算复杂度较高的算法作为测试方法,虽然不能代表全部,但是很大程度上展示大家平时开发过程中所面临的常见场景和问题。考虑到演示和理解,就选择了查找100000以内的所有素数的个数的算法作为演示。另外也顺带演示如何在WinRT下实现多编程语言和技术之间的协作吧。
关于基本知识和算法吧详细的说明,请自行搜索各大引擎吧(关键词:prime、素数),这里我就列举在各个语言下我的简单实现吧,其中包括使用普通算法和并行计算的两个版本。
第一部分,从目前.NET主流来看吧,以C#为例,普通版本,这个没什么多说的,就是从前往后看某个数是不是素数:
并行版本稍微复杂一点点,选择Parallel.For来并行执行一个从1至n/2的并行循环(我这里偷懒了一下,没有处理奇偶数的情况,因为我的调用时传入的都是偶数),发现是素数,使用Interlocked辅助方法给计数增加1。
第一种场景,直接嵌入算法到C# WinRT App工程,执行结果如下(单位毫秒):
第二种场景,将C#算法包装在一个类库里(注意是CLR类库,只能在C#/VB直接通用),在C# WinRT App工程中调用这个类库,执行结果如下(单位毫秒):
第三种场景,将C#算法包装到一个Windows Runtime Component(WRC)中,在C# WinRT App工程中调用这个WRC类库,执行结果如下(单位毫秒):
第四种场景,将C#算法包装到一个Windows Runtime Component(WRC)中,在WinJS App工程中调用这个WRC类库,执行结果如下(单位毫秒):
小结:以上是从.NET角度来进行的比较,很容易看出第一次CLR加载在这里性能损耗表现的很明显,完成加载之后性能将稳定在一定范围内波动;另外,并行计算在纯算法的应用中有很明显的性能优势。
第二部分,接下来我们回归Native环境,这里我依然使用普通和并行计算两种来尝试,普通的依然没什么可说的(实际上和C#的没区别,除了关键字不一样)。
并行版本,需要注意的是C++ lambda的传值和作用域问题,其他的和C#的没区别:
第一种场景,直接将C++算法放到C++ WinRT App中使用,执行结果如下(单位毫秒):
第二种场景,将C++算法包装在DLL中,在C++ WinRT App中使用,执行结果如下(单位毫秒):
第三种场景,将C++算法包装在动态连接库Dll中,在C# WinRT App中通过PInvoke来调用,执行结果如下(单位毫秒):
第四种场景,将C++算法包装在静态链接库Lib中,在C++ WinRT App中调用,执行结果如下(单位毫秒):
第五种场景,将C++算法包装在Windows Runtime Component(WRC)中,在C# WinRT App中调用,执行结果如下(单位毫秒):
第六种场景,将Windows Runtime Component(WRC)中,在WinJS App中调用,执行结果如下(单位毫秒):
第七种场景是将C++算法包装在Windows Runtime Library(WRL,基于COM的底层开发)中,然后在任何一种WinRT App中调用,可以预见这是一种很强大的方式,但同时也是最费解的一种方式,我成功的包装了普通算法的COM版,但是尝试了很长时间不能成功实现并行运算的版本,也就放弃在这里展示了,如果你知道如何在WRL中实现并行计算并返回IAsyncOperation<T>,请不吝赐教。
小结:基于C++的实现在适用性、稳定性和执行效率上无可挑剔,如果对于所有细节(包括第一次启动)的效率考虑,C++是优先的;如果考虑到C++的复杂度,如果项目对性能要求可以适当放松但对进度要求很高的时候,选择CLR会比较容易控制的;如果原来已有的Web项目向WinRT迁移,那么前段展示则可以考虑使用WinJS+HTML来实现,后台算法根据需要选择C++或者CLR。
第三部分,如果所有的算法全部运行在JavaScript中,那么其性能如何呢?这里我先买个关子,留待你自己去探究和发掘。
总结,WinRT在编程语言的选择性上有着非常好的灵活性,在做选择的时候需要充分考虑自己的要求,比如性能、比如工期、比如经验等等。对于全新项目,在有经验的情况下,追求极致性能的首先首当其冲是C++,如果考虑到经验和掌控,可以选择使用C++做底层,选择相对容易上手的C#/VB或者HTML+JS做界面的方法;如果项目工期要求很紧,或者从老系统迁移,那么这时候更多的考虑是使用已有资源,直到性能瓶颈的时候才采取措施——以C++重写性能瓶颈来解决,当然,如果没有C++经验,也可以考虑使用C#/VB来实现WRC以包装核心逻辑,从而提升运行效率。
附以上测试源代码和测试工程,点击这里下载。
* 本文在葡萄城控件技术团队博客同时发布
这里我选择运行计算复杂度较高的算法作为测试方法,虽然不能代表全部,但是很大程度上展示大家平时开发过程中所面临的常见场景和问题。考虑到演示和理解,就选择了查找100000以内的所有素数的个数的算法作为演示。另外也顺带演示如何在WinRT下实现多编程语言和技术之间的协作吧。
关于基本知识和算法吧详细的说明,请自行搜索各大引擎吧(关键词:prime、素数),这里我就列举在各个语言下我的简单实现吧,其中包括使用普通算法和并行计算的两个版本。
第一部分,从目前.NET主流来看吧,以C#为例,普通版本,这个没什么多说的,就是从前往后看某个数是不是素数:
private static int CountingInternal(int n) { var numprimes = 1; for (var i = 3; i <= n; i += 2) { var isPrime = true; var limit = Math.Ceiling(Math.Sqrt(i)) + 1; for (var j = 3; j < limit; j += 2) { if (i%j == 0) { isPrime = false; break; } } if (isPrime) { numprimes++; } } return numprimes; }
并行版本稍微复杂一点点,选择Parallel.For来并行执行一个从1至n/2的并行循环(我这里偷懒了一下,没有处理奇偶数的情况,因为我的调用时传入的都是偶数),发现是素数,使用Interlocked辅助方法给计数增加1。
private static int CountingParallel(int n) { var numprimes = 1; Parallel.For(1, n/2, i => { if (IsPrime(i*2 + 1)) { Interlocked.Increment(ref numprimes); } }); return numprimes; } public static bool IsPrime(int n) { if (n%2 == 0) return false; var limit = (int) (Math.Ceiling(Math.Sqrt(n)) + 1); for (var i = 3; i < limit; i += 2) { if (n%i == 0) { return false; } } return true; }
第一种场景,直接嵌入算法到C# WinRT App工程,执行结果如下(单位毫秒):
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 14.0299 | 9.0005 | 9.1825 | 8.0021 | 11.0181 |
并行 | 6.0008 | 2.0004 | 2.9993 | 2.0014 | 3.999 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 12.0299 | 9.0019 | 10.003 | 9.0014 | 9.00017 |
并行 | 6.0008 | 2 | 3.0003 | 2.9997 | 1.9995 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 11.9904 | 9.0032 | 9 | 9。0028 | 9.00149 |
并行 | 6.0008 | 1.9817 | 1.9985 | 1.9993 | 2 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 11 | 9 | 8 | 9 | 8 |
并行 | 4 | 1 | 1 | 3 | 2 |
第二部分,接下来我们回归Native环境,这里我依然使用普通和并行计算两种来尝试,普通的依然没什么可说的(实际上和C#的没区别,除了关键字不一样)。
static int CountingInternal(int n) { auto numprimes = 1; for (auto i = 3; i <= n; i += 2) { auto isPrime = true; auto limit = ceil(sqrt(i)) + 1; for (auto j = 3; j < limit; j += 2) { if (i%j == 0) { isPrime = false; break; } } if (isPrime) { numprimes++; } } return numprimes; }
并行版本,需要注意的是C++ lambda的传值和作用域问题,其他的和C#的没区别:
static bool IsPrime(int n) { if (n%2 == 0) return false; auto limit = (int) (ceil(sqrt(n)) + 1); for(auto i=3; i<limit; i+=2) { if(n%i == 0) { return false; } } return true; } static int CountingParallel(int n) { auto numprimes = 1; parallel_for(1, n/2, [&](int i) { if(IsPrime(i*2+1)) { InterlockedIncrement((volatile unsigned long*)&numprimes); } }); return numprimes; }
第一种场景,直接将C++算法放到C++ WinRT App中使用,执行结果如下(单位毫秒):
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 8.0019 | 7.9991 | 8.0209 | 8.9843 | 8.0181 |
并行 | 1.9794 | 1.998 | 1.9994 | 1.984 | 2.0003 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 9 | 9 | 9 | 8 | 9 |
并行 | 3 | 2 | 3 | 2 | 2 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 9 | 9 | 8 | 9 | 9 |
并行 | 3 | 2 | 3 | 2 | 3 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 8 | 8 | 8 | 9 | 9 |
并行 | 2 | 3 | 3 | 2 | 3 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 8.0014 | 8.0191 | 8.0293 | 8.0019 | 9.0291 |
并行 | 1.9994 | 1.9999 | 1.998 | 1.9994 | 2.99982 |
执行次数 | 1(启动) | 2 | 3 | 4 | 5 |
普通 | 9 | 8 | 9 | 8 | 8 |
并行 | 2 | 2 | 3 | 2 | 3 |
小结:基于C++的实现在适用性、稳定性和执行效率上无可挑剔,如果对于所有细节(包括第一次启动)的效率考虑,C++是优先的;如果考虑到C++的复杂度,如果项目对性能要求可以适当放松但对进度要求很高的时候,选择CLR会比较容易控制的;如果原来已有的Web项目向WinRT迁移,那么前段展示则可以考虑使用WinJS+HTML来实现,后台算法根据需要选择C++或者CLR。
第三部分,如果所有的算法全部运行在JavaScript中,那么其性能如何呢?这里我先买个关子,留待你自己去探究和发掘。
总结,WinRT在编程语言的选择性上有着非常好的灵活性,在做选择的时候需要充分考虑自己的要求,比如性能、比如工期、比如经验等等。对于全新项目,在有经验的情况下,追求极致性能的首先首当其冲是C++,如果考虑到经验和掌控,可以选择使用C++做底层,选择相对容易上手的C#/VB或者HTML+JS做界面的方法;如果项目工期要求很紧,或者从老系统迁移,那么这时候更多的考虑是使用已有资源,直到性能瓶颈的时候才采取措施——以C++重写性能瓶颈来解决,当然,如果没有C++经验,也可以考虑使用C#/VB来实现WRC以包装核心逻辑,从而提升运行效率。
附以上测试源代码和测试工程,点击这里下载。
* 本文在葡萄城控件技术团队博客同时发布
相关文章推荐
- WinRT开发语言的功能和效率
- WinRT开发语言的功能和效率
- WinRT开发语言的功能和效率
- WinRT开发语言的功能和效率
- WEB开发框架系列教程 (三)页面功能开发(2)
- 【Qt编程】基于Qt的词典开发系列<十四>自动补全功能
- 【小试插件开发】给Visual Studio装上自己定制的功能来提高代码调试效率
- 简单快速开发C\S架构程序用最简单的不分层最快的效率达到功能要求的例子程序FrmCommnets
- 【linux下c语言服务器开发系列5】功能齐全的聊天室 sever [IO复用+多进程+信号处...
- Android高效率编码-第三方SDK详解系列(二)——Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能
- 【Qt编程】基于Qt的词典开发系列<十四>自动补全功能
- Office365开发系列——开发一个全功能的Word Add-In
- Office365开发系列——开发一个全功能的Word Add-In
- iOS开发系列--Quartz 2D绘制2D图形和Core Image中强大的滤镜功能
- 手机安全卫士开发系列(1)——功能列表
- 功能齐全、效率一流的免费开源数据库导入导出工具(c#开发,支持SQL server、SQLite、ACCESS三种数据库),每月借此处理数据5G以上
- IOS开发系列—iOS 8增强的自动布局功能(一)
- Java Socket编程系列(二)开发带回声功能的Server和Client
- C# WinForm开发系列 - ComboBox扩展,如可以实现复选功能
- Winform开发框架之客户关系管理系统(CRM)的开发总结系列1-界面功能展示