遗留项目中C#代码可能存在的性能问题
我最近开始在一个新项目中工作,我们有数千行遗留代码。我们面临几个性能问题。我决定看一下代码,看到了以下内容。有一门课:遗留项目中C#代码可能存在的性能问题,c#,.net,performance,.net-3.5,processing-efficiency,C#,.net,Performance,.net 3.5,Processing Efficiency,我最近开始在一个新项目中工作,我们有数千行遗留代码。我们面临几个性能问题。我决定看一下代码,看到了以下内容。有一门课: public class BaseDataAccess { private Database dB; public Database DB { get { if (dB == null) { dB = DatabaseFactory.Crea
public class BaseDataAccess
{
private Database dB;
public Database DB
{
get
{
if (dB == null)
{
dB = DatabaseFactory.CreateDatabase();
}
return dB;
}
}
}
以及许多继承自前一个基类的子类。在内部,这些其他类使用DB属性,如下所示:
DataSet ds = DB.ExecuteDataSet(spGetCustomersSortedByAge);
最后,还有一个巨大的类(5000行代码),包含数十种方法,如下所示:
public void ProcessPayments()
{
try
{
List<Employee> employees = new EmployeesDA().SelectAll(null);
foreach (Employee employee in employees)
{
employee.Account = new MovementsDA().SelectAll(employee.Id, DateTime.Now);
...
City city = new CitiesDA().Select(zone.cityId);
...
Management m = new ManagmentDA().Select(city.id);
}
}
catch (Exception ex)
{
...
}
}
public void ProcessPayments()
{
尝试
{
List employees=new EmployeesDA()。选择全部(空);
foreach(员工中的员工)
{
employee.Account=newmovementsda().SelectAll(employee.Id,DateTime.Now);
...
城市=新城市数据()。选择(zone.cityId);
...
管理m=新建管理数据()。选择(city.id);
}
}
捕获(例外情况除外)
{
...
}
}
注意在前面的方法中,EmployeesDA、MovementsDA、CitiesDA和ManagementDA都是BaseDataAccess的继承者,在内部使用各自的DB属性。还要注意的是,它们经常在foreach循环中被实例化(在两个嵌套级别中多次)
我认为实例化本身是可疑的,但我更关心的是这里的数据库连接发生了什么?是否每个DA实例化后都会打开一个新的底层连接?这个代码有多糟糕
作为我考虑的解决方案的一个附带说明,如果这段代码应该被修复:我考虑将每个构造函数都设置为私有的,这样编译器开始抱怨实例化,并通过调用GetInstance方法重构实例化(singleton模式)避免重新创建对象和底层连接。但是,我不确定这是否在某种程度上也是危险的,例如,如果连接可能被关闭。当前的代码没有这个问题,因为实例化一直在发生。通常错误地认为对象构造是昂贵的。它比基本算法或其他机器级别的东西要昂贵得多,但不可能是性能问题的直接来源 例如,在循环中使用装箱整数是浪费的,但是在每个循环中构造一个Employee对象与重用一个可变Employee对象相比,并不会带来有意义的性能优势 许多垃圾收集器能够在这样的循环中重用对象内存帧。实际上,在循环的每个过程中分配并覆盖一个对象帧
在这种特定情况下,如果DA具有显著的初始化成本,则可能会产生成本。如果是这样的话,我会重构代码,在循环之外创建这些代码。我不会使用实际的静态单例。如果需要,我会使用依赖项注入来管理单例对象。静态单例是有效的全局变量,是有状态耦合和模块化分解的邀请。通常错误地认为对象构造是昂贵的。它比基本算法或其他机器级别的东西要昂贵得多,但不可能是性能问题的直接来源 例如,在循环中使用装箱整数是浪费的,但是在每个循环中构造一个Employee对象与重用一个可变Employee对象相比,并不会带来有意义的性能优势 许多垃圾收集器能够在这样的循环中重用对象内存帧。实际上,在循环的每个过程中分配并覆盖一个对象帧
在这种特定情况下,如果DA具有显著的初始化成本,则可能会产生成本。如果是这样的话,我会重构代码,在循环之外创建这些代码。我不会使用实际的静态单例。如果需要,我会使用依赖项注入来管理单例对象。静态单例是有效的全局变量,是对有状态耦合和模块化分解的邀请。这种方法有很多错误,但是如果
DatabaseFactory.CreateDatabase()代码>方法为每个调用返回一个新的、已连接的数据库连接,那么您就有一个很大的连接问题。另一个问题是事务支持。ProcessPayments
不应该确保所有事情都发生在一次交易中吗?或者每个员工至少有一个事务,或者类似的事情?正确的处理方法是开始让程序中的连接状态可见,这样就必须对其进行管理。@LasseV.Karlsen,DatabaseFactory是一个.NET类,但我不确定每次CreateDatabase执行时都会发生什么。所以我希望有人能在这里解释一下。如果这里的数据库对象只是在执行查询时打开连接,然后关闭连接,对于许多开放的连接,您应该没有问题,但是您仍然应该考虑事务的问题。这种方法有很多问题,但是如果<代码>数据库工厂。代码>方法为每个调用返回一个新的、已连接的数据库连接,那么您就有一个很大的连接问题。另一个问题是事务支持。ProcessPayments
不应该确保所有事情都发生在一次交易中吗?或者每个员工至少有一个事务,或者类似的事情?正确的处理方法是开始让程序中的连接状态可见,这样就必须对其进行管理。@LasseV.Karlsen,DatabaseFactory是一个.NET类,但我不确定每次CreateDatabase执行时都会发生什么。因此,我希望有人能给我们一些启示。如果这里的数据库对象只是在执行q时打开连接