前不久为用户做了一个小工具,把数据中心的数据发布到其它相应的数据库.到用户的测试机上一跑,
10分钟左右,内存用光(1.5G)
,跟踪看了一下
IBATISN.NET 1.6.1
的源码,哈哈。。。找着根了
一、根位置 MappedStatement.cs
ibaits的数据真实操作都交给了这个类。其中用一大堆与select相关操作的方法以及insert update delete相关方法,内存泄漏就在这些方法上。简单看一下ExecuteInsert(insert)方法的代码:
二、原因 IDispose 接口得显示调用
using并不能释放这些非托管资源
三、解决方法:看上面代码
四、总结
以前用ibaits怎么就没有发现在呢?
我想这与项目的实际应用场景有关,问题一直都存在,只是没有显现吧了。
大多数据时候,用户的输入参数只有几个,相对较少,而且调用频度应该不高。
而这个应用场景走的却是另一个极端:
调用频度极高:
数据中心实时采集4家公司的数据,且数据更新高峰在开收盘前后,中午休市最为集中,每天的数据更新在3000K左右,这些数据要及时发布到5个数据库中
参数超多:
近200张表中有50多张账务相关的表字段个数在100到230之间
这些字段最终是要转换成 INSERT 与 UPDATE 语句中的参数, 怪不得程序显示超多OarcleParamter 对象无法回收,它不多才怪。。。
不过还好,加了上面的代码后,程序内存近期还没超过150M,多在100M左右
如果你也有用IBAITS.NET,你可要小心了。。
这个问题其实是由 IDispose 接口引起的, 不知道JAVA是什么样子,源码还没仔细看
JAVA版本的3.0出来时间也不短了,易用性比 IBATIS.NET 1.6.1 要强太多了。
不知道 .NET 版本的更新什么时候出。。。
一、根位置 MappedStatement.cs
ibaits的数据真实操作都交给了这个类。其中用一大堆与select相关操作的方法以及insert update delete相关方法,内存泄漏就在这些方法上。简单看一下ExecuteInsert(insert)方法的代码:
// 初始化 command 的参数 _preparedCommand.Create(request, session, this.Statement, parameterObject); // 用 using 处理 command using (IDbCommand command = request.IDbCommand) { try { if (_statement is Insert) { generatedKey = command.ExecuteNonQuery(); } // Retrieve output parameter if the result class is specified else if (_statement is Procedure && (_statement.ResultClass != null) && _sqlMap.TypeHandlerFactory.IsSimpleType(_statement.ResultClass)) { ......// 省 } if (selectKeyStatement != null && selectKeyStatement.isAfter) { IMappedStatement mappedStatement = _sqlMap.GetMappedStatement(selectKeyStatement.Id); generatedKey = mappedStatement.ExecuteQueryForObject(session, parameterObject); ObjectProbe.SetMemberValue(parameterObject, selectKeyStatement.PropertyName, generatedKey, request.DataExchangeFactory.ObjectFactory, request.DataExchangeFactory.AccessorFactory); } //ExecutePostSelect(request); RetrieveOutputParameters(request, session, command, parameterObject); } // 下面这个 finally 段是我加上去的,我不确定 command 的 dispose是否会调用相关Paramters中对象相应的 dispose 方法,所以就用了下面这个,因为程序中显示大量IDataParamter 对象无法回收 finally { if (command.Parameters.Count > 0){ MethodInfo mi = command.Parameters[0].GetType().GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public); if (mi != null) for (int i = 0; i < command.Parameters.Count; i++) mi.Invoke(command.Parameters[i], null); } command.Dispose(); } }
二、原因 IDispose 接口得显示调用
using并不能释放这些非托管资源
三、解决方法:看上面代码
四、总结
以前用ibaits怎么就没有发现在呢?
我想这与项目的实际应用场景有关,问题一直都存在,只是没有显现吧了。
大多数据时候,用户的输入参数只有几个,相对较少,而且调用频度应该不高。
而这个应用场景走的却是另一个极端:
调用频度极高:
数据中心实时采集4家公司的数据,且数据更新高峰在开收盘前后,中午休市最为集中,每天的数据更新在3000K左右,这些数据要及时发布到5个数据库中
参数超多:
近200张表中有50多张账务相关的表字段个数在100到230之间
这些字段最终是要转换成 INSERT 与 UPDATE 语句中的参数, 怪不得程序显示超多OarcleParamter 对象无法回收,它不多才怪。。。
不过还好,加了上面的代码后,程序内存近期还没超过150M,多在100M左右
如果你也有用IBAITS.NET,你可要小心了。。
这个问题其实是由 IDispose 接口引起的, 不知道JAVA是什么样子,源码还没仔细看
JAVA版本的3.0出来时间也不短了,易用性比 IBATIS.NET 1.6.1 要强太多了。
不知道 .NET 版本的更新什么时候出。。。