最近在調試一個算法,想通過改變算法的參數看看結果有什么變化。 碰到一個麻煩的事情是,從磁盤加載、構建數據需要15分鍾。這就比較討厭了,也就是說我每次調一個參數前都要等15分鍾啟動時間?
於是我就想,能不能開一個datahost進程專門加載數據。我在別的進程調試參數,但需要用數據時就直接從datahost進程中加載現成的數據。 這樣的話我只需要從磁盤加載一次數據。 於是找了一下, c#有個叫IPC(inter process communication)的功能可以實現同一台機器上的不同進程間通信。
注意我這里的scenario:我需要進程間通信“數據對象”, 而不是消息。 通信消息比較好辦,就傳一個string流就行了。而我需要傳遞的是數據對象,比如一個Dictionary, 或者自定義class。
IPC的大致過程是這樣的:datahost進程先綁定一個對象,client根據對象的uri去訪問對象類, 並且調用該類的方法。datahost進程接收到從client發來的調用,就會實例化一個對象(注意,在這個時候才開始實例化一個對象,這也是我的代碼里使用static的原因),並且執行相關的函數,再把結果返回給client。 注意執行過程是在datahost端的。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IPCServer { public class DataObj : MarshalByRefObject { public static Dictionary<string, int> salary; public static string company; public static int counter; public static int constructerCnt = 0; public static void LoadData() { company = "Microsoft"; salary = new Dictionary<string, int>(); salary.Add("lianjx", 3); salary.Add("uncle", 5); counter = 0; } public Dictionary<string, int> GetSalary() { return DataObj.salary; } public DataObj() { DataObj.constructerCnt++; Console.WriteLine("Constructer...{0}", DataObj.constructerCnt); } } }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.Remoting; 5 using System.Runtime.Remoting.Channels; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace IPCServer 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 IpcServerChannel channel = new IpcServerChannel("ServerChannel"); 17 ChannelServices.RegisterChannel(channel, false); 18 DataObj.LoadData(); 19 DataObj.salary.Add("jian", 23); 20 DataObj.salary.Add("xun", 22); 21 RemotingConfiguration.RegisterWellKnownServiceType(typeof(DataObj), "DataObj", WellKnownObjectMode.SingleCall); 22 23 Console.WriteLine("press anykey to exit"); 24 Console.ReadKey(); 25 } 26 } 27 }
1 using IPCServer; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Runtime.Remoting.Channels; 6 using System.Runtime.Remoting.Channels.Ipc; 7 using System.Text; 8 using System.Threading.Tasks; 9 10 namespace IPCClient 11 { 12 class Program 13 { 14 static void Main(string[] args) 15 { 16 IpcClientChannel channel = new IpcClientChannel(); 17 ChannelServices.RegisterChannel(channel, false); 18 19 DataObj obj = null; 20 21 for (int t = 0; t < 1; t++) 22 { 23 Console.WriteLine("t={0}", t); 24 try 25 { 26 obj = (DataObj)Activator.GetObject(typeof(DataObj), "ipc://ServerChannel/DataObj"); 27 } 28 catch (Exception e) 29 { 30 Console.WriteLine(e.Message); 31 } 32 33 if (obj == null) 34 { 35 Console.WriteLine("could not locate server"); 36 } 37 else 38 { 39 foreach (var pair in obj.GetSalary()) 40 { 41 Console.WriteLine("{0},{1}", pair.Key, pair.Value); 42 } 43 Console.WriteLine("counter = {0}", obj.GetSalary()); 44 DataObj.counter++; 45 } 46 } 47 48 Console.WriteLine("Mission Complete!"); 49 Console.ReadKey(); 50 } 51 } 52 }
事實上結果並沒有加速。估計IPC也是把對象序列化后傳遞,再反序列化的吧。 桑心。
next steps: 尋找一種直接讀其他進程的內存空間的途徑。。。
