共享内存使用的纠结
共享内存所要达到的目的就是两个或多个本地进程可以读取某个进程里的数据,这个进程里的数据就相当于缓存。
具体案例:由于在添加数据到数据库时,需要根据已有的数据,来判断是否要添加,添加一条,可能要查询几十次数据库来进行判断,频繁的查询数据库,I/O狂升,数据的处理速度,也达不到想要的效果,因此,就想到把数据库里的2GB的数据,全部放到内存。但是,问题又来了,每次初始化这些数据到内存要耗费2个小时,并且,处理数据的程序会经常的改动,重新运行的话,单单初始化数据到内存都要用去2个小时。
种种考虑,不得不把数据初始化到内存的部分独立出来,google了一下,找到了好几种的解决办法。
1.WCF—Your own data sharing/caching windows service based on TCP/IP (Socket server)
2.Memory mapped files Working with memory mapped files in .NET 4
3.IPC or RPC - Take a look at this examples
4.DCOM - Distributed Component Object Model
5.Native DLL - How do I share data in my DLL with an application or with other DLLs?
这里只试了两种办法,如果读者有兴趣,可以试下别的办法,办法确实比问题多,呵呵。
第一种:WCF 这种方式,写起来代码很方便,直接把数据放到Dictionary里,取的时候,用linq带上条件就可以方便的得到想要的数据。尽管如此,wcf的互通需要通过proxy,基于net pipe或tcp协议,速度上仍然有些慢。
第二种:Memory mapped files这种方式,由于它读写数据都是通过byte数组来进行,因此对数据的处理(分组,排序)就显得力不从心。更重要的是,加载到内存的数据,你如果想修改、删除,也是相当麻烦,也只能对它说再见。
Memory mapped files测试代码:
static MemoryMappedFile mmf = MemoryMappedFile.CreateNew("test", 1024 * 1024 ); //申请1MB的空间 static MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(); static void Main(string[] args) { Dictionary<string, string> pos = new Dictionary<string, string>(); //保存数据的位置 Dictionary<string, string> dict = new Dictionary<string, string>(); dict.Add("chinaz.com", "www.cnbogs.com,www.baidu.com"); dict.Add("cnblogs.com", "www.hjenglish.com,blog.39.net,blog.china.alibaba.com"); dict.Add("hao123.com", "baidu.com,google.com"); long start = 0; foreach (string s in dict.Keys) { WriteData(start, dict[s]); pos.Add(s, start.ToString() + ":" + (start + dict[s].Length + 1).ToString()); start += dict[s].Length + 2; } foreach (string s in pos.Keys) { string[] p = pos[s].Split(':'); string result = ReadData(long.Parse(p[0]), long.Parse(p[1])); Console.WriteLine(result); } Console.Read(); } static void WriteData(long position, string str) { byte[] bb = Encoding.ASCII.GetBytes(str); accessor.WriteArray(position, bb, 0, bb.Length); } static string ReadData(long position, long end) { byte byteValue; StringBuilder str = new StringBuilder(); do { byteValue = accessor.ReadByte(position); if (byteValue != 0) { char asciiChar = (char)byteValue; str.Append(asciiChar); } position++; if (position >= end) { break; } } while (byteValue != 0); return str.ToString(); }
现在在想怎么能把wcf模式下的通信性能提上去。