使用 JointCode.Shuttle 提升跨 AppDomain 通讯的性能

JointCode.Shuttle 是一个用于进程内 AppDomain 间通讯的服务架构(不支持跨进程),它旨在取代运行时库提供的 MarshalByrefObject 的功能。git

本文比较了 MarshalByrefObject 与 JointCode.Shuttle 的跨 AppDomain 对象访问的性能。github

背景知识缓存

咱们知道跨 AppDomain 调用的性能是十分低下的,由于在这种状况下对象之间的交互不是直接的,而是要穿越一个边界 (AppDomain)。安全

为了穿越这个边界,首先须要将对象转换(术语称为“marshal”,即封送)成一个能够传输的形态(好比,在 .NET Remoting 中对象将被打包成一个可序列化的 ObjRef 实例——MarshalByrefObject 中的 ByRef 指的就是 ObjRef 这种形态);而后,当数据流到达目标 AppDomain 时,还要执行解封 (unmarshal) 操做将其还原为内存中的对象。这个过程是很是耗时的,由于其中可能涉及到各类反射、序列化/反序列化、安全检查等等。能够想象获得,若是一个程序频繁发起跨 AppDomain 调用,那么它的性能恐怕将会受到严重影响。架构

好在咱们通常不须要和 AppDomain 打交道,所以也没必要太多关注它。然而,有的时候咱们确实不得不使用 AppDomain。好比说在插件环境下,咱们有可能须要动态加载/卸载程序集,在这种状况下 AppDomain 是不二选择,由于咱们知道在 .net/mono 中,程序集是不能单独卸载的,只能随着 AppDomain 一块儿卸载。性能

为了提升 AppDomain 间通讯的性能,做者开发了 JointCode.Shuttle。测试

测试spa

为了比较 JointCode.Shuttle 和 MarshalByrefObject 的跨 AppDomain 调用性能,而且尽可能了解可能会影响性能的各个因素,我编写了一个测试。该测试向咱们展现了两种类型的结果:.net

  • 反复建立远程服务对象并调用对象方法:这是为了从总体上比较两者的调用性能(包括建立对象和调用方法的开销)。
  • 建立远程服务对象,并将其缓存到一个本地字段中,而后反复调用对象方法:这是单纯为了比较两者的远程方法调用性能(仅仅测试调用方法的开销)。由于方法调用时可能须要传递各类不一样类型和数量的参数,这些都会影响最终性能。须要特别指出的是,这种作法仅仅是为了方便测试,在实践中是不能将远程服务对象的引用缓存到字段的。由于远程服务对象的生命期受控于远端,它有可能在远端已经超时失效并被垃圾回收,而本地调用者对此并不知情,仍旧继续调用其方法,此时将会抛出异常。

 

下面这张图是部分测试结果:插件

 JointCode.Shuttle与MarshalByObject性能对比

若是您对测试代码自己感兴趣,可移步前往 此处 下载测试源码(测试名称:ShuttleDomain性能测试)。

相关文章
相关标签/搜索