Мой календарь генерация кода происходит медленно. Как я могу улучшить его?


У меня модель я создал для создания iCal и необходимые JSON с помощью jQuery плагин календарь Полный календарь на работу. Когда я отображения страницы, генерация JSON и занимает около 7 секунд. Сам запрос выполняется в течение всего нескольких микросекунд. Так я знаю, что мой код-это проблема.

Я пытался сделать формат, как то, что полный календарь рассчитывает, таким образом, почему я написал код, как я сделал. Я думаю, что ниже-это проблема. Любой мысли о том, где я могу улучшить это?

#region Event
public class Event
{
    public string Title { set; get; }
    public string Description { set; get; }
    public string URL { set; get; }
    public string UID { set; get; }
    public DateTime DateTimeStamp { set; get; }
    public DateTime CreatedDateTime { set; get; }
    public DateTime Start { set; get; }
    public DateTime End { set; get; }
    public bool AllDay { set; get; }
}
#endregion

public class Calendar
{
    #region Model
    public string CalendarName { set; get; }
    public string Product { set; get; }
    public string TimeZone { set; get; }
    public List<Event> Events { private set; get; }
    #endregion

    /// <summary>
    /// Creates a calendar json string.
    /// </summary>
    /// <returns></returns>
    public string ToFullCalendarJsonString()
    {
        StringBuilder sb = new StringBuilder();

        sb.Append("[");

        int count = Events.Count;
        int i = 0;

        foreach (Event eventItem in Events)
        {
            sb.Append("{");
            sb.AppendFormat("\"title\":\"{0}\",", eventItem.Title);
            sb.AppendFormat("\"allDay\":\"{0}\",", eventItem.AllDay);

            if (eventItem.AllDay)
            {
                sb.AppendFormat("\"start\":\"{0}T00:00:00\",", eventItem.Start.ToString("yyyy-MM-dd"));
                sb.AppendFormat("\"end\":\"{0}T00:00:00\",", eventItem.End.ToString("yyyy-MM-dd"));
            }
            else
            {
                sb.AppendFormat("\"start\":\"{0}T{1}\",", eventItem.Start.ToString("yyyy-MM-dd"), eventItem.Start.ToString("HH:mm:ss"));
                sb.AppendFormat("\"end\":\"{0}T{1}\",", eventItem.End.ToString("yyyy-MM-dd"), eventItem.End.ToString("HH:mm:ss"));
            }
            sb.AppendFormat("\"url\":\"{0}\"", eventItem.URL);
            sb.Append("}");

            i++;

            if (i < count)
            {
                sb.Append(",");
            }
        }

        sb.Append("]");

        return sb.ToString();
    }


978
8
задан 17 марта 2011 в 07:03 Источник Поделиться
Комментарии
3 ответа

Я просто где-то читал , что AppendFormat() может быть медленнее, чем просто присоеденить() звонки. Будучи в шоке, прочитав это, я решил расследовать.

За 1.000.000 пустых событий время являются:


  • С AppendFormat: 9297 клещей

  • Без AppendFormat: 8268 клещей

Это значительная разница в 11%!

Я предполагаю, что это связано с поиск аргументов, и такие. Было бы неплохо, если AppendFormat() бы быть перекомпилированы с помощью append() звонки только по умолчанию.

Это код:

    /// <summary>
/// Creates a calendar json string.
/// </summary>
/// <returns></returns>
public string ToFullCalendarJsonStringFaster()
{
StringBuilder sb = new StringBuilder();

sb.Append( "[" );

int count = Events.Count;
int i = 0;

foreach ( Event eventItem in Events )
{
sb.Append( "{" );

sb.Append("\"title\":\"");
sb.Append(eventItem.Title);
sb.Append("\",");
sb.Append("\"allDay\":\"");
sb.Append(eventItem.AllDay);
sb.Append("\",");

if ( eventItem.AllDay )
{
// My test never comes here, so I left it out.
}
else
{
sb.Append("\"start\":\"");
sb.Append(eventItem.Start.ToString("yyyy-MM-dd"));
sb.Append("T");
sb.Append(eventItem.Start.ToString("HH:mm:ss"));
sb.Append("\",");

sb.Append("\"end\":\"");
sb.Append(eventItem.End.ToString("yyyy-MM-dd"));
sb.Append("T");
sb.Append(eventItem.End.ToString("HH:mm:ss"));
sb.Append("\",");
}
sb.Append("\"url\":\"");
sb.Append(eventItem.URL);
sb.Append("\"");
sb.Append( "}" );

i++;

if ( i < count )
{
sb.Append( "," );
}
}

sb.Append( "]" );

return sb.ToString();
}

Также применяться ранее ответы Snowbear это:


  • Используя гггг-мм-ддтчч:мм:СС в формат строки, дает дополнительную скорость разница 5%

  • Предварительное определение класса StringBuilder размер, дает дополнительную скорость разница 6%

В общем, после применения всех изменений, код 22% быстрее. :)

Итог, тут скорее не "магическое" решение, которое может сделать его пойти с так много событий, но вы можете значительно улучшить скорость. Я предлагаю вам выполнить обработку на BackgroundWorker.


... этого становится еще смешнее. Изменение форматирования даты следующим образом:

//sb.Append(eventItem.Start.ToString( "yyyy-MM-ddTHH:mm:ss" ) );
sb.Append(eventItem.Start.Year);
sb.Append("-");
sb.Append(eventItem.Start.Month);
sb.Append("-");
sb.Append(eventItem.Start.Day);
sb.Append("T");
sb.Append(eventItem.Start.Hour);
sb.Append(":");
sb.Append(eventItem.Start.Minute);
sb.Append(":");
sb.Append(eventItem.Start.Second);
sb.Append("\",");

... дает еще увеличение скорости и делает это 34% быстрее в общей сложности. Может замедлить
снова, если вы нуждаетесь в более конкретных форматирования.


Остерегайтесь: это последнее обновление является, вероятно, результате предоставления неверной. Я задал вопрос о правильном использования в PLINQ.

Я не использовал параллельный LINQ (PLINQ), так еще. Но это казалось хорошим применение. После замены на:

Events.AsParallel().AsOrdered().ForAll( eventItem =>
{
...
} );

Я получаю общую скорость увеличить на 43%, еще 9% быстрее. :) Это на двухъядерном процессоре. Компьютер с большим количеством ядер должны работать лучше. Я не знаю, как PLINQ работает точно так же, но я думаю, он может работать даже быстрее, если одна итерация не надо ждать от другого. В то StringBuilder и я представлены в виде блокад. У кого-нибудь есть более эффективные подходы, чем Форалл()?

11
ответ дан 18 марта 2011 в 01:03 Источник Поделиться

Пару хитростей для повышения производительности (у меня около +10%, не так много правда):

1) выделить то StringBuilder размер. Вы можете примерно посчитать его общая площадь, как события.Граф * charsPerEvent
2) в этой строке: СБ.AppendFormat("\"конец\":\"{0}Т{1}\",", eventItem.Конец.Метод toString("гггг-ММ-ДД"), eventItem.Конец.Метод toString("чч:мм:СС")); совместить два параметра в 1, используя следующую строку формата даты: гггг-мм-ддтчч:мм:СС

Также я сомневаюсь, что вы сможете получить представление. Может можно обойти это как-то? Например, кэширование результатов. Также можно попробовать вместо создания новой строки, просто пишите в ответ через HttpHandler, так если Asp.Net в MVC все-таки позволяет сделать это легко. Не уверен, что это поможет также.

6
ответ дан 17 марта 2011 в 09:03 Источник Поделиться

Обратите внимание, что это не по теме (не решение codereview, но представление о том, как решить проблему производительности.)

Мне трудно поверить, что это действительно узкое место

Вы уверены, что это действительно узкое место? Вы можете проверить это путем возвращения постоянный поддельных строку JSON.

  string fake2000Events = @"{.......}";

public string ToFullCalendarJsonString()
{
return fake2000Events
}

Если производительность значительно лучше, чем расчет реальных данных, то вы можете думать о кэшировании результатов.

2
ответ дан 18 марта 2011 в 06:03 Источник Поделиться