程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 插件系統中跨域調用的性能和“一個簡單的性能計數器”的使用

插件系統中跨域調用的性能和“一個簡單的性能計數器”的使用

編輯:關於.NET

系統大概的流程如下:從數據中心接收到數據包(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模式哦。

 1namespace 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)

1namespace 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是模擬的"規則"

1namespace 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模擬的向規則傳遞數據時的接口

1namespace AppDomainPerformanceDemo
2{
3    public interface IInterface
4    {
5        void FunA();
6    }
7}

測試結果如下:

當時考慮MarshalByRefObject的性能的時候,大概有三點

1。調用函數本身執行的時間,這裡ImplementA的FunA函數的函數體是空的。故不考慮。

2。調用函數的時候,輸入和輸出參數序列化的時間,這裡FunA輸入和輸出參數都是void,故不考慮。

3。方法跨域調用的時間----這個測試主要針對這個。

我非常奇怪的就是為何ImplementA和RemoterProxy的在Across AppDomain方式下調用方法的速度為何 不同??

望各位大牛多多拍磚,望大牛們下載一下代碼,給小的解答一下上面的問題。

隨文源碼:http://www.bianceng.net/dotnet/201212/661.htm

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved