Как можно оптимизировать этот код? - PullRequest
0 голосов
/ 10 ноября 2009

У меня есть метод, который по сути преобразует данные в список объектов, которые я называю «Сумки». Этот код вызывается много раз за сеанс, при этом одновременно выполняется много сеансов, а иногда и тысячи строк. Из-за этого мне нужно, чтобы это было как можно быстрее. У меня есть XML-файл, который содержит сопоставления DataColumn и Property. Основной метод оптимизации - ConvertRowToBag - передаваемый параметр типа является типом, который наследуется от BagBase.

Это длинный кусок кода, но любые советы будут очень полезны.

public class BagBase
{
    /// <summary>
    /// Dictionary of properties and names
    /// </summary>
    private static Dictionary<string, PropertyInfo> propertyDictionary = new Dictionary<string, PropertyInfo>();

    /// <summary>
    /// Table of column/property mappings
    /// </summary>
    private static DataTable mappings = new DataTable("Mappings");

    /// <summary>
    /// Returns true if the map exists
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    private static bool MappingExists(string columnName, Type type)
    {
        DataRow [] rows = BagBase.mappings.Select(String.Format("Type = '{0}' and ColumnName = '{1}'", type.Name, columnName));
        return (rows != null && rows.Length > 0);
    }

    /// <summary>
    /// Converts the table to bags.
    /// </summary>
    /// <param name="table">The table.</param>
    /// <param name="outputType">Type of the output.</param>
    /// <returns></returns>
    protected static List<BagBase> ConvertTableToBags(DataTable table, Type outputType)
    {
        Trace.TraceInformation(String.Format("ConvertTableToBags : table={0} Type={1}", table.TableName, outputType.Name));

        // Create an empty list
        List<BagBase> result = new List<BagBase>();

        // Iterate through the rows
        foreach (DataRow row in table.Rows)
        {
            // Add to the list
            result.Add(ConvertRowToBag(outputType, row));
        }

        Trace.TraceInformation("ConvertTableToBags Finished.");

        return result;
    }

    /// <summary>
    /// Converts the row to bag.
    /// </summary>
    /// <param name="outputType">Type of the output.</param>
    /// <param name="row">The row.</param>
    /// <returns></returns>
    protected static BagBase ConvertRowToBag(Type outputType, DataRow row)
    {
        // Create an instance of the child class and store in the base
        BagBase bag = Activator.CreateInstance(outputType) as BagBase;

        // Iterate through the columns
        foreach (DataColumn column in row.Table.Columns)
        {
            // If this column has been mapped
            if (BagBase.MappingExists(column.ColumnName, outputType))
            {
                PropertyInfo property;

                string columnProperty = String.Format("{0}={1}", column.ColumnName, outputType.Name);

                // Get the property as defined in the map
                if (!propertyDictionary.ContainsKey(columnProperty))
                {
                    // Get the property
                    property = outputType.GetProperty(BagBase.GetColumnMapping(column.ColumnName, outputType));

                    // Add the property to the dictionary
                    propertyDictionary.Add(columnProperty, property);
                }
                else
                {
                    property = propertyDictionary[columnProperty];
                }

                if (property != null)
                {
                    if (!row.IsNull(column))
                    {
                        // Set the value to the in the table
                        if (property.PropertyType.BaseType != null && property.PropertyType.BaseType == typeof(Enum))
                        {
                            if (column.DataType != typeof(String))
                            {
                                property.SetValue(bag, Enum.ToObject(property.PropertyType, row[column]), null);
                            }
                            else
                            {
                                property.SetValue(bag, Enum.ToObject(property.PropertyType, Convert.ToChar(row[column])), null);
                            }
                        }
                        else if (property.PropertyType == typeof(DateTime?))
                        {
                            property.SetValue(bag, (DateTime?)row[column], null);
                        }
                        else
                        {
                            property.SetValue(bag, Convert.ChangeType(row[column], property.PropertyType), null);
                        }
                    }
                    else // No nulls
                    {
                        if (column.DataType == typeof(String))
                        {
                            property.SetValue(bag, String.Empty, null);
                        }
                    }

                    // Generate the unique class.property name
                    string propertyKey = String.Format("{0}.{1}", outputType.Name, property.Name);
                    if (!columnCaptions.ContainsKey(propertyKey))
                    {
                        // Add to the caption map
                        columnCaptions.Add(propertyKey, column.Caption);
                    }
                }
            }
            else
            {
                // If this column isn't mapped, add it to Other information
                if (bag.OtherInformation == null)
                {
                    bag.OtherInformation = new Dictionary<string, string>();
                }

                bag.OtherInformation.Add(column.ColumnName, !row.IsNull(column) ? row[column].ToString() : String.Empty);
            }
        }

        return bag;
    }
}

Ответы [ 2 ]

5 голосов
/ 10 ноября 2009

Используйте профилировщик. У нас нет возможности узнать, что на самом деле занимает больше всего времени в вашем коде.

Попытки оптимизировать построчно просто бесполезны, и многие, похоже, этого не знают. Компьютеры всегда ждут ресурс, иногда это ЦП или дисковый ввод-вывод, а часто это пользователь. Чтобы ускорить выполнение любого фрагмента кода, найдите узкие места с помощью профилировщика и постарайтесь ускорить этот код.

2 голосов
/ 10 ноября 2009

Помимо общего совета "использовать профилировщик", вероятно, существует не одно узкое место, а либо серия медленных вызовов, либо сама структура процедуры создает ненужные итерации. С первого взгляда:

  • Выбор по данным, как правило, не очень эффективен.
  • Отражение несет с собой много накладных расходов, похоже, что вы зависите от него, но если вы сможете ограничить его область действия, вы, вероятно, получите более высокую общую производительность.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...