WinRT开发语言的功能和效率
WinRT開發(fā)有著多種選擇性,就編程語(yǔ)言這一點(diǎn)就表現(xiàn)的很突出;這里就這一點(diǎn) 深入展開,探討在WinRT開發(fā)之初如何依據(jù)各 個(gè)編程語(yǔ)言的特性、功能和效率來(lái)對(duì) 產(chǎn)品的技術(shù)方向做出選擇。
這里我選擇運(yùn)行計(jì)算復(fù)雜度較高的算法作為測(cè)試方法,雖然不能代表全部,但 是很大程度上展示大家平時(shí)開發(fā)過(guò)程中所面臨的常見場(chǎng)景 和問(wèn)題。考慮到演示和 理解,就選擇了查找100000以內(nèi)的所有素?cái)?shù)的個(gè)數(shù)的算法作為演示。另外也順帶演 示如何在WinRT下實(shí)現(xiàn)多編程語(yǔ)言和技 術(shù)之間的協(xié)作吧。
關(guān)于基本知識(shí)和算法吧詳細(xì)的說(shuō)明,請(qǐng)自行搜索各大引擎吧(關(guān)鍵 詞:prime、素?cái)?shù)),這里我就列舉在各個(gè)語(yǔ)言下我的簡(jiǎn)單實(shí)現(xiàn)吧,其中包括使用 普通算法和并 行計(jì)算的兩個(gè)版本。
?
第一部分,從目前.NET主流來(lái)看吧,以C# 為例,普通版本,這個(gè)沒什么多說(shuō)的,就是從前往后看某個(gè)數(shù)是不是素?cái)?shù):
并行版本稍微復(fù)雜一點(diǎn)點(diǎn),選擇Parallel.For來(lái)并行執(zhí)行一個(gè)從1至n/2的并行 循環(huán)(我這里偷懶了一下,沒有處理奇 偶數(shù)的情況,因?yàn)槲业恼{(diào)用時(shí)傳入的都是 偶數(shù)),發(fā)現(xiàn)是素?cái)?shù),使用Interlocked輔助方法給計(jì)數(shù)增加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; }第一種場(chǎng)景,直接嵌入算法到C# WinRT App工程,執(zhí)行結(jié)果如下(單位毫 秒):
| 執(zhí)行次數(shù) | 1(啟動(dòng)) | 2 | 3 | 4 | 5 |
| 普通 | 14.0299 | 9.0005 | 9.1825 | 8.0021 | 11.0181 |
| 并行 | 6.0008 | 2.0004 | 2.9993 | 2.0014 | 3.999 |
第二種場(chǎng)景,將C#算法包裝在一個(gè)類庫(kù)里(注意 是CLR類庫(kù),只能在C#/VB直接通用),在C# WinRT App工程中調(diào)用這個(gè)類庫(kù),執(zhí)行 結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | 1(啟動(dòng)) | 2 | 3 | 4 | 5 |
| 普通 | 12.0299 | 9.0019 | 10.003 | 9.0014 | 9.00017 |
| 并行 | 6.0008 | 2 | 3.0003 | 2.9997 | 1.9995 |
第三種場(chǎng)景,將C#算法包裝到一個(gè)Windows Runtime Component(WRC)中,在C# WinRT App工程中調(diào)用這個(gè)WRC類庫(kù),執(zhí)行結(jié) 果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?11.9904 | ?9.0032 | ?9 | ?9。0028 | 9.00149? |
| 并行? | ?6.0008 | ?1.9817 | ?1.9985 | ?1.9993 | ?2 |
第四種場(chǎng)景,將C#算法包裝到一個(gè)Windows Runtime Component(WRC)中,在WinJS App工程中調(diào)用這個(gè)WRC類庫(kù),執(zhí)行結(jié)果如 下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?11 | ?9 | ?8 | ?9 | 8 |
| 并行? | ?4 | ?1 | ?1 | ?3 | ?2 |
小結(jié):以上是從.NET角度來(lái)進(jìn)行的比較,很容易 看出第一次CLR加載在這里性能損耗表現(xiàn)的很明顯,完成加載之后性能將穩(wěn)定在一 定范 圍內(nèi)波動(dòng);另外,并行計(jì)算在純算法的應(yīng)用中有很明顯的性能優(yōu)勢(shì)。
?
第二部分,接下來(lái)我們回歸Native環(huán)境,這里我 依然使用普通和并行計(jì)算兩種來(lái)嘗試,普通的依然沒什么可說(shuō)的(實(shí)際上和C#的沒 區(qū) 別,除了關(guān)鍵字不一樣)。
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的傳值 和作用域問(wèn)題,其他的和C#的沒區(qū)別:
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; }第一種場(chǎng)景,直接將C++算法放到C++ WinRT App 中使用,執(zhí)行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?8.0019 | 7.9991 | ?8.0209 | ?8.9843 | ?8.0181? |
| 并行? | ?1.9794 | ?1.998 | ?1.9994 | ?1.984 | ?2.0003 |
第二種場(chǎng)景,將C++算法包裝在DLL中,在C++ WinRT App中使用,執(zhí)行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?9 | 9 | ?9 | ?8 | ?9? |
| 并行? | ?3 | 2 | ?3 | ?2 | ?2 |
第三種場(chǎng)景,將C++算法包裝在動(dòng)態(tài)連接庫(kù)Dll中,在C# WinRT App中通過(guò) PInvoke來(lái)調(diào)用,執(zhí)行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?9 | 9 | ?8 | ?9 | ?9? |
| 并行? | ?3 | 2 | ?3 | ?2 | ?3 |
第四種場(chǎng)景,將C++算法包裝在靜態(tài)鏈接庫(kù)Lib中,在C++ WinRT App中調(diào)用,執(zhí) 行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?8 | 8 | ?8 | ?9 | ?9? |
| 并行? | ?2 | 3 | ?3 | ?2 | ?3 |
第五種場(chǎng)景,將C++算法包裝在Windows Runtime Component(WRC)中,在C# WinRT App中調(diào)用,執(zhí)行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?8.0014 | 8.0191 | ?8.0293 | ?8.0019 | ?9.0291 |
| 并行? | ?1.9994 | 1.9999 | ?1.998 | ?1.9994 | ?2.99982 |
第六種場(chǎng)景,將Windows Runtime Component(WRC)中,在WinJS App中調(diào)用, 執(zhí)行結(jié)果如下(單位毫秒):
| 執(zhí)行次數(shù) | ?1(啟動(dòng)) | ?2 | 3 | 4 | 5? |
| 普通 | ?9 | 8 | ?9 | ?8 | ?8? |
| 并行? | ?2 | 2 | ?3 | ?2 | ?3 |
第七種場(chǎng)景是將C++算法包裝在Windows Runtime Library(WRL,基于COM的底 層開發(fā))中,然后在任何一種WinRT App中調(diào)用,可以預(yù)見這是一種很強(qiáng)大的方 式,但同時(shí)也是最費(fèi)解的一種方式,我成功的包裝了普通算法的COM版,但是嘗試 了很長(zhǎng)時(shí)間不能成功實(shí)現(xiàn)并行運(yùn)算 的版本,也就放棄在這里展示了,如果你知道 如何在WRL中實(shí)現(xiàn)并行計(jì)算并返回 IAsyncOperation<T>,請(qǐng)不吝賜教。
小結(jié):基于C++的實(shí)現(xiàn)在適用性、穩(wěn)定性和執(zhí)行效率上無(wú)可挑剔,如果對(duì)于所有 細(xì)節(jié)(包括第一次啟動(dòng))的效率考慮,C++是優(yōu)先 的;如果考慮到C++的復(fù)雜度, 如果項(xiàng)目對(duì)性能要求可以適當(dāng)放松但對(duì)進(jìn)度要求很高的時(shí)候,選擇CLR會(huì)比較容易 控制的;如果原來(lái)已有的Web項(xiàng)目 向WinRT遷移,那么前段展示則可以考慮使用 WinJS+HTML來(lái)實(shí)現(xiàn),后臺(tái)算法根據(jù)需要選擇C++或者CLR。
?
第三部分,如果所有的算法全部運(yùn)行在 JavaScript中,那么其性能如何呢?這里我先買個(gè)關(guān)子,留待你自己去探究和發(fā) 掘。
?
總結(jié),WinRT在編程語(yǔ)言的選擇性上有著非常好的 靈活性,在做選擇的時(shí)候需要充分考慮自己的要求,比如性能、比如工期、比如經(jīng) 驗(yàn)等 等。對(duì)于全新項(xiàng)目,在有經(jīng)驗(yàn)的情況下,追求極致性能的首先首當(dāng)其沖是 C++,如果考慮到經(jīng)驗(yàn)和掌控,可以選擇使用C++做底層,選擇相對(duì)容易上手 的 C#/VB或者HTML+JS做界面的方法;如果項(xiàng)目工期要求很緊,或者從老系統(tǒng)遷移,那 么這時(shí)候更多的考慮是使用已有資源,直到性能瓶頸的時(shí) 候才采取措 施——以C++重寫性能瓶頸來(lái)解決,當(dāng)然,如果沒有C++經(jīng)驗(yàn),也可以考 慮使用C#/VB來(lái) 實(shí)現(xiàn)WRC以包裝核心邏輯,從而提升運(yùn)行效率。
?
附以上測(cè)試源代碼和測(cè)試工程,點(diǎn)擊這里下載。
總結(jié)
以上是生活随笔為你收集整理的WinRT开发语言的功能和效率的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 分享网页加载速度优化的一些技巧?
- 下一篇: 手机设备文件对传