我被赋予了重写一些用C#编写的库的任务,这样一旦启动完成就没有分配。
我刚接触到一个项目,每隔30秒通过OdbcConnection执行一些数据库查询。我一直只使用.ExecuteReader()创建一个OdbcDataReader。是否有任何模式(如SocketAsyncEventArgs套接字模式)允许您重用自己的OdbcDataReader?还是其他一些避免分配的聪明方法?
我没有费心去学习LINQ,因为所有的dbs都是基于Oracle的,而且我检查过的最后一个,没有正式的Linq To Oracle提供商。但是如果在Linq中有办法做到这一点,我可以使用其中一个第三方。
更新
我认为我没有明确说明无分配要求的原因。我们有一个关键线程正在运行,非冻结非常重要。这是一个近乎实时的交易应用程序,我们确实看到一些Gen 2集合冻结最多100毫秒。 (我也听说过在C#中以相同的方式编写游戏)。有一个后台线程执行一些合规性检查,每30秒运行一次。它现在进行数据库查询。查询非常慢(大约500毫秒返回所有数据),但这没关系,因为它不会干扰关键线程。除非工作线程正在分配内存,否则会导致GC冻结所有线程。
我被告知所有库(包括这个库)在启动后都无法分配内存。无论我是否同意,这是签署支票的人的要求:)。
现在,显然有一些方法可以在没有分配的情况下将数据导入此过程。我可以设置另一个进程并使用套接字将其连接到此进程。使用新的SocketAsyncEventArgs模式,新的.NET 3.5套接字经过专门优化,根本不进行分配。 (实际上,我们正在使用它们连接到多个系统,并且从不会看到它们中的任何GC。)然后有一个预先分配的字节数组,它从套接字读取并遍历数据,在此过程中不分配任何字符串。 (我不熟悉.NET中其他形式的IPC,所以我不确定内存映射文件和命名管道是否分配)。
但如果有一种更快的方式来完成这个无分配查询而不经历所有麻烦,我更喜欢它。
答案 0 :(得分:3)
您无法重复使用IDataReader
(或OdbcDataReader
或SqlDataReader
或任何同等类别。它们旨在仅与单个查询一起使用。这些对象封装了一个记录集,所以一旦你获得并迭代它,就没有任何意义了。
无论如何,创建数据阅读器是一项非常便宜的操作,与实际执行查询的成本相比,这个操作非常小。我无法看到这种“无分配”要求的合理原因。
我甚至可以说,重写一个库几乎不可能,以便分配无内存。即使是装箱整数或使用字符串变量这样简单的东西也会分配一些内存。即使在某种程度上可以重用读者(它不是,正如我所解释的),它仍然必须再次向数据库发出查询,这将需要以准备查询的形式进行内存分配,发送它通过网络,再次检索结果等
避免内存分配根本不是一个实际目标。如果确定某些特定操作耗尽了太多内存,最好还是避免特定类型的内存分配。
答案 1 :(得分:2)
对于这样的要求,你确定你选择像C#这样的高级语言吗? 您不能说您正在使用的.NET库函数是否在内部分配内存。该标准不保证,因此如果他们不在当前版本的.NET框架中使用分配,他们可能会在稍后开始这样做。
答案 2 :(得分:1)
我建议您分析应用程序以确定花费时间和/或内存的位置。不要猜 - 你只会猜错。