简体   繁体   中英

Possible performance issues with C# code in a legacy project

I started working recently in a new project where we have thousands of lines of legacy code. We are facing several performance issues. I decided to take a look at the code and saw the following. There's a class:

public class BaseDataAccess
{
    private Database dB;

    public Database DB
    {
        get
        {
            if (dB == null)
            {
                dB = DatabaseFactory.CreateDatabase();
            }
            return dB;
        }
    }
}

And many descendant classes which inherit from the previous base class. Internally, those other classes make use of the DB property, like this:

DataSet ds = DB.ExecuteDataSet(spGetCustomersSortedByAge);

Finally, there's a huge class (5000 lines of code) with tens of methods like the following:

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

    }

Note in the previous method EmployeesDA, MovementsDA, CitiesDA and ManagmentDA all are inheritors of BaseDataAccess and internally use their respective DB properties. Also note they are constantly being instantiated inside foreach loops (many times within 2 levels of nesting).

I think the instantiation itself is suspicious but I'm more concerned about what's going on with the database connections here? Is every DA instantiated opening a new underlying connection? How bad is this code?

As a side note about the solution I was considering in case this code should be fixed: I was considering making every constructor private so the compiler starts complaining about the instantiations and refactor the instantiations with calls to the GetInstance method (singleton pattern) to avoid the recreation of the objects and underlying connections. But, I'm not sure if this could also be dangerous in some way, for example, if the connections may get closed. The current code doesn't have that problem because of the instantiatons happening all the time.

It's a common misconception that object construction is expensive. It's much more expensive than base arithmetic or other machine-level things, but isn't likely the direct source of performance issues.

Using boxed integers for a loop is wasteful for example, but constructing an Employee object in each vs reusing a mutable Employee object isn't going to give meaningful performance advantages.

Many garbage collectors are capable of object memory frame reuse in loops like this. In effect a single object frame is allocated and overwritten on each pass of the loop.

In this specific case there may be a cost if the DA's have significant initialization costs. If that is the case I would refactor the code to create those once outside the loop. I would not use actual static singletons. I would use dependency injection to manage singleton objects if you need it. Static singletons are effectively global variables and are an invitation to stateful coupling and the break down of modularity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM