遗留项目中C#代码可能存在的性能问题

时间:2016-01-01 21:09:32

标签: c# .net performance .net-3.5 processing-efficiency

我最近开始在一个新项目中工作,我们有数千行遗留代码。我们正面临几个性能问题。我决定看看代码并看到以下内容。有一节课:

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)
        {
                ...
        }

    }

在上一个方法中注意,EmployeesDA,MovementsDA,CitiesDA和ManagmentDA都是BaseDataAccess的继承者,并在内部使用它们各自的DB属性。还要注意它们在foreach循环中不断被实例化(在嵌套的2个级别内多次)。

我认为实例化本身是可疑的,但我更担心这里的数据库连接发生了什么?是否每个DA实例化都会打开一个新的底层连接?这段代码有多糟糕?

作为关于解决方案的旁注,我正在考虑以防这个代码应该修复:我正在考虑使每个构造函数都是私有的,因此编译器开始抱怨实例化并通过调用GetInstance方法重构实例化(单例模式)避免重新创建对象和底层连接。但是,我不确定这在某种程度上是否也会有危险,例如,如果连接可能会关闭。由于实例化一直在发生,当前的代码没有这个问题。

1 个答案:

答案 0 :(得分:0)

对象构造昂贵是一种常见的误解。它比基本算术或其他机器级别的东西贵得多,但不太可能是性能问题的直接来源。

例如,对循环使用盒装整数是浪费的,但是在每个中构造一个Employee对象与重用可变的Employee对象并不会带来有意义的性能优势。

许多垃圾收集器能够像这样在循环中重用对象内存帧。实际上,在循环的每次传递中分配并覆盖单个对象帧。

在这种特定情况下,如果DA具有显着的初始化成本,则可能存在成本。如果是这种情况,我会重构代码以在循环之外创建那些代码。我不会使用实际的静态单例。如果需要,我会使用依赖注入来管理单例对象。静态单例是有效的全局变量,是对有状态耦合和模块化破坏的邀请。