下面的内容大部分都是来源于//build/ 2012上面《Deep Dive into the kernel of .NET on Windows Phone 8》的主题演讲,翻译能力不怎么好,有问题欢迎指正。
Windows Phone 8仍然是NETCF吗?
WP8以前,Windows Phone使用的是.NET Compact Framework(CE内核的限制)。即使是WP7上的Silverlight,其运行环境也是NETCF,而非CoreCLR。到WP8时,这种情况已经得到改善,Silverlight的执行环境已经从原来的NETCF切换到CoreCLR。这样一来我们可以得到什么东西呢,下面我们看看。
关于NETCF
关于NETCF,可以戳一下这篇文章。
NETCF是专为设备设计的便携式小型.NET CLR。.NET CF不是对桌面版本.NET Framework的部分简单平移,把.NET Framework完整移植到移动设备上并不是.NET CF的目标,尽管表面上看起来有些内容和完整版的.NET Framework是一致的,但是其实现方式可能很不一样。
关于CoreCLR
关于Silverlight中的CoreCLR,可以戳一下这篇文章。
WP8中引入CoreCLR引擎和改进的GC,这里的CoreCLR包含了很多与.NET Framework 4.5相同的特性,相比WP7中使用的.NET Compact Framework,CoreCLR更快、更高效。改进的GC有助于应用程序更快地运行。所有的改进都是为了用户可以得到更快的启动时间和更短的反应时间。
Windows Phone 8有什么改进?
- 更好的功能
- 本地代码游戏引擎
- 跨平台的代码共享
- 流畅、反应迅速的应用
- 更强的性能
- 更快的应用启动时间
- 更快的应用执行时间
- 更快的应用反应
Windows Phone 8应用支持不同语言的混合编程
本地代码制作的游戏引擎可以很方便地移植到WP8上,相比以往的P/Invoke调用方式,新的调用方式(利用WinRT API移植)的效率更高,性能更好。
快速移植本地C++代码
对于一个已经完成的C++库,核心代码并不需要进行修改,我们所需要做的只是利用WinRT重新书写我们的对外接口。
示例:GNUGo代码库的移植示例,只需要使用WinRT中的C++/CX重新写一个接口即可在C#代码中直接调用,十分方便。
快速共享已有代码
对于开发过程中可能遇到的面对不同平台,以往我们的代码可能需要针对每种平台制作一份工程。为了解决这个问题,新的开发工具中提供了Portable Library Project,只需要建立一个工程,即可面对不台的平台输出相应的代码。
异步操作:为了更流畅的体验
异步操作的需要:如果没有异步,我们的UI反应将有可能十分缓慢,严重影响了用户体验。
WP8已经提供了很多方便的异步编程API,我们需要做的是将API封装成异步形式(TASK)。
示例:
void SynchronousMethod()
{
for (int i = 0; i <= 5; ++i)
Dowork(GetWorkd());
}
async void AsynchronousMethod()
{
for (int i = 0; i <= 5; ++i)
DoWork(await GetWorkTask());
}
加速应用启动时间:云中编译(Compiler in the Cloud)
在WP8上,应用启动时间缩短了两倍,原因是:使用了Compiler in the Cloud[2]技术。在应用提交至应用商店之后,用户下载应用前,应用商店中的编译器将会预先编译优质高效的ARM机器码,此方法大大缩短了WP8上的应用启动时间,让应用程序得到更快的运行(当然,这种技术对WP7的应用也有效)。
机器码生成方式比较
JIT | NGEN | |
平台 | Phone 7.5 | 桌面 |
机器码生成 | 程序执行前 | 程序安装时 |
机器码重用 | 否 | 是 |
更快的启动速度 | 否 | 是 |
部署简单 | 是 | 否 |
类库更新时会否影响 | 是 | 否 |
WP 7.5时,机器码的生成利用JIT,在程序执行前进行机器码的编译。此方法生成的机器码无法得到重用,每次生成之后,应用重启都需要重新生成,虽然程序的运行速度得到一定的保障,但启动时间并没有得到提高。
NGEN,对于桌面程序,生成ASM码的过程对用户影响并不大,在安装的时候只需要花费几分钟时间即可。由于我们并不知道程序运行时使用的部分机器码是什么,因此NGEN使用时,将会对类库全部NGEN生成ASM码。
综上,在移动设备上的预编译代价太大,要么消耗程序安装时间,要么就影响程序启动时间。
Cascaded Re-Compilation(级联重编译):如果一个托管的DLL更新了,则依赖于此DLL的DLL\EXE将全部需要更新,这样的代价太大了。理想情况下,类库文件都是比较稳定且基本不会更新的。我们所做的事只是在新的DLL文件中加入我们自己的新类型或者与这些库文件进行静态链接。但是这种情况下由于最底层的库文件更新了,基类容易出现问题而导致相关的链接出现问题(Fragile Base Class Problem)。
例子
// 原来的代码
class Base
{
int i;
string s;
virtual void baseFunc() { }
}
class AppDerived: Base
{
int j;
int foo(int a) { return a+j; }
}
// 更新后的代码 The Fragile Base Class "Base"
class Base
{
int i;
string s;
int k;
virtual void baseFunc() { }
}
代码更新前,代码编译出来的Native Code都很正常,没有问题。但是如果我们的基类代码更新后,派生类如果不进行重新生成Native Code的步骤,则我们在基类中添加的int j则会在Native Code中与原来的AppDerived代码生成的Native Code产生冲突。
一个十分简单而又强大的想法
- 编译没有变化的本地代码
- 在所有可能改变的地方添加占位符(MDIL: Machine Dependent IL),在链接阶段时使用MDIL代码相应代码
- 安装的时候生成本地代码取代MDIL
- 当类库更新时,只需要快速地重新链接一下本地代码
MDIL在哪里被编译?
当应用提交至应用市场之后,用户下载前MDIL编译器将会使MDIL得到编译,生成MDIL Assembly。
此技术支持WP 7.5应用程序。
加速应用执行速度:优化编译器
WP8中,编译器得到了改进,应用程序的运行速度得到了不小的提高,具体可以参考下面的图表。
增强GC内存管理
- GC延迟更低
- 多核分配
- 增强对象生存周期跟踪
- 第三代GC