系统大概的流程是这样子的:从数据中心接收到数据包(1万~3万(个)/秒,使用WCF)可以被不同的应用场景使用,每个应用场景的业务逻辑各不相同,而每个场景的接受数据包部分的代码是相通的,于是使用一个容器将所有的"场景的dll"通过反射加载,同时容器接受所有的数据包并把他们分发给"场景的dll",接收数据的功能,自然被抽象成了Interface。透彻一点讲就是一个插件系统,只不过这个插件有点儿大而已,达到整个系统都是个插件而已。这个容器我们暂时叫他“引擎”,而这个"场景的dll"我们暂且叫他“规则”。
请到此处下载代码
系统大概的流程如下:从数据中心接收到数据包(1万~3万(个)/秒,使用WCF)可以被不同的应用场景使用,每个应用场景的业务逻辑各不相同,而每个场景的接收数据包部分的代码是相同的,于是使用一个容器将所有的"应用场景的dll"通过反射加载,同时容器接收所有的数据包并把他们分发给"应用场景的dll",接收数据的功能,自然被抽象成了Interface。透彻一点讲就是一个插件系统,只不过这个插件有点儿大而已,大到整个系统都是个插件。这个容器我们暂时叫他“引擎”,而这个"场景的dll"我们暂且叫他“规则”。
我的理想做法是:每一个规则(一个或多个dll)都单独放在一个文件夹下面,并且有自己的配置文件。当引擎启动的时候,根据引擎的配置为每个规则创建一个新的AppDomain,并且还为该AppDomain设置配置文件,同时让这个新的AppDomain加载相对应的dll。引擎的CurrentDomain里面保存着每个规则的MarshalByRefObject,当引擎接收到数据的时候,就把这些数据根据一些条件分发到相对应的规则当中。俄,引擎看起来有点像一个IIS啊!!!
等等,这么美妙的想法,这么容易就可以实现?! 我是不是忘记了什么??哦 我忘记了那些规则的MarshalByRefObject每秒钟是否能承受1万~3万次的调用(这里的调用就是传递数据包)。
[下午系统测试得时候,性能技术器显示每秒钟仅仅2千个左右的包被处理,剩下的都丢了。。。。。。疯狂的郁闷中
]
自从上次net技术大会回来,每天都挺忙,好多讲课还没来得及回味,看到老赵和eaglet都CodeTimer了,惭愧啊,不过刚好拿过来用吧
。测试代码如下:
1。FunA() FunB() FunC() FunD() 为测试代码,class RemoterProxy是为了创建远程对象更容易一些,不是Proxy模式哦。

Code
1
namespace AppDomainPerformanceDemo
2

{
3
class Program
4
{
5
const int COUNT = 500000;
6
7
static void Main( string[] args )
8
{
9
FunA();
10
FunB();
11
FunC();
12
FunD();
13
14
Console.ReadLine();
15
}
16
17
18
static void FunC()
19
{
20
RemoterProxy remoterProxy = new RemoterProxy();
21
CodeTimer.Time( "RemoterProxy: Same AppDomain", COUNT, remoterProxy.FunTest );
22
}
23
24
static void FunD()
25
{
26
AppDomain domain = AppDomain.CreateDomain( "NewAppDomain" );
27
RemoterProxy remoterProxy = (RemoterProxy)domain.CreateInstanceAndUnwrap( Assembly.GetExecutingAssembly().FullName, "AppDomainPerformanceDemo.RemoterProxy" ); ;
28
CodeTimer.Time( "RemoterProxy: Across AppDomain", COUNT, remoterProxy.FunTest );
29
AppDomain.Unload( domain );
30
}
31
32
static void FunB()
33
{
34
IInterface inter = new ImplementA();
35
CodeTimer.Time( "ImplementA: Same AppDomain", COUNT, inter.FunA );
36
}
37
38
static void FunA()
39
{
40
AppDomain domain = AppDomain.CreateDomain( "NewAppDomain" );
41
RemoterProxy remoterProxy = (RemoterProxy)domain.CreateInstanceAndUnwrap( Assembly.GetExecutingAssembly().FullName, "AppDomainPerformanceDemo.RemoterProxy" );;
42
IInterface inter = remoterProxy.CreateInstance( "AppDomainPerformanceDemo.ImplementA", "MyImplement", BindingFlags.CreateInstance, null );
43
CodeTimer.Time( "ImplementA: Across AppDomain", COUNT, inter.FunA );
44
AppDomain.Unload( domain );
45
46
}
47
}
48
49
public class RemoterProxy : MarshalByRefObject
50
{
51
public IInterface CreateInstance( string typeName, string assemblyName, BindingFlags bindingFlags, object[] constructorParams )
52
{
53
Assembly owningAssembly = Assembly.Load( assemblyName );
54
55
IInterface instanceHandler = owningAssembly.CreateInstance( typeName) as IInterface;//, false, bindingFlags, null, constructorParams, null, null ) as IInterface;
56
57
return instanceHandler;
58
}
59
60
public void FunTest()
61
{
62
}
63
}
64
65
66
}
67
2。CodeTimer使用eaglet的,但是把IAction修改了。(我的机器是xp,vs2008)

Code
1
namespace AppDomainPerformanceDemo
2

{
3
public static class CodeTimer
4
{
5
[DllImport( "kernel32.dll", SetLastError = true )]
6
static extern bool GetThreadTimes( IntPtr hThread, out long lpCreationTime,
7
out long lpExitTime, out long lpKernelTime, out long lpUserTime );
8
9
[DllImport( "kernel32.dll" )]
10
static extern IntPtr GetCurrentThread();
11
12
private static long GetCurrentThreadTimes()
13
{
14
long l;
15
long kernelTime, userTimer;
16
GetThreadTimes( GetCurrentThread(), out l, out l,
17
out kernelTime, out userTimer );
18
return kernelTime + userTimer;
19
}
20
21
static CodeTimer()
22
{
23
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
24
Thread.CurrentThread.Priority = ThreadPriority.Highest;
25
26
}
27
28
public static void Time( string name, int iteration, Action action )
29
{
30
if( String.IsNullOrEmpty( name ) )
31
{
32
return;
33
}
34
35
if( action == null )
36
{
37
return;
38
}
39
40
// 1.
41
ConsoleColor currentForeColor = Console.ForegroundColor;
42
Console.ForegroundColor = ConsoleColor.Yellow;
43
Console.WriteLine( name );
44
45
// 2.
46
GC.Collect( GC.MaxGeneration, GCCollectionMode.Forced );
47
int[] gcCounts = new int[GC.MaxGeneration + 1];
48
for( int i = 0; i <= GC.MaxGeneration; i++ )
49
{
50
gcCounts[i] = GC.CollectionCount( i );
51
}
52
53
// 3.
54
Stopwatch watch = new Stopwatch();
55
watch.Start();
56
long ticksFst = GetCurrentThreadTimes(); //100 nanosecond one tick
57
58
for( int i = 0; i < iteration; i++ ) action();
59
long ticks = GetCurrentThreadTimes() - ticksFst;
60
watch.Stop();
61
62
// 4.
63
Console.ForegroundColor = currentForeColor;
64
Console.WriteLine( "\tTime Elapsed:\t" +
65
watch.ElapsedMilliseconds.ToString( "N0" ) + "ms" );
66
67
Console.WriteLine( "\tCall: \t" +
68
(iteration/watch.ElapsedMilliseconds)*1000 + "/s" );
69
70
71
Console.WriteLine( "\tCPU time:\t" + ticks.ToString( "N0" ) + "ns" );
72
73
// 5.
74
for( int i = 0; i <= GC.MaxGeneration; i++ )
75
{
76
int count = GC.CollectionCount( i ) - gcCounts[i];
77
Console.WriteLine( "\tGen " + i + ": \t\t" + count );
78
}
79
80
Console.WriteLine();
81
82
}
83
}
84
85
}
3。ImplementA是模拟的"规则"

Code
1
namespace AppDomainPerformanceDemo
2

{
3
public class ImplementA : MarshalByRefObject, IInterface
4
{
5
IInterface 成员#region IInterface 成员
6
7
public void FunA()
8
{
9
10
}
11
12
#endregion
13
}
14
}
4。IInterface模拟的向规则传递数据时的接口

Code
1
namespace AppDomainPerformanceDemo
2

{
3
public interface IInterface
4
{
5
void FunA();
6
}
7
}
测试结果如下:
当时考虑MarshalByRefObject的性能的时候,大概有三点
1。调用函数本身执行的时间,这里ImplementA的FunA函数的函数体是空的。故不考虑。
2。调用函数的时候,输入和输出参数序列化的时间,这里FunA输入和输出参数都是void,故不考虑。
3。方法跨域调用的时间----这个测试主要针对这个。
我非常奇怪的就是为何ImplementA和RemoterProxy的在Across AppDomain方式下调用方法的速度为何不同??
望各位大牛多多拍砖,望大牛们下载一下代码,给小的解答一下上面的问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架