알고리즘에서 흥미로운 문제점을 발견했을 때 개발 사이트에있는 이벤트 뷰어 응용 프로그램의 성능 문제를 조사했습니다. 그런 다음 두 가지 알고리즘을 테스트하기 위해 간단한 테스트 프로젝트를 만들었습니다. 이 프로그램은 기본적으로 EventLog
클래스를 사용하여 Windows 이벤트 로그를 검색 한 다음 해당 로그를 쿼리 가능 EventLogItem
엔티티로 변환합니다.앞으로/뒤로 루프 성능 분석
이 작업은 두 개의 다른 루프를 사용하여 수행되고 시간이 지정됩니다. 첫 번째 (뒤로) 루프는 목록의 마지막 항목의 인덱스에서 시작하여 항목을 변환 한 다음 인덱스를 줄입니다. 이 메서드는 다음과 같이 정의됩니다.
private static void TranslateLogsUsingBackwardLoop()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var originalLogs = EventLog.GetEventLogs();
var translatedLogs = new List<EventLogItem>();
Parallel.ForEach<EventLog>(originalLogs, currentLog =>
{
for (int index = currentLog.Entries.Count - 1; index >= 0; index--)
{
var currentEntry = currentLog.Entries[index];
EventLogItem translatedEntry = new EventLogItem
{
MachineName = currentEntry.MachineName,
LogName = currentLog.LogDisplayName,
CreatedTime = currentEntry.TimeGenerated,
Source = currentEntry.Source,
Message = currentEntry.Message,
Number = currentEntry.Index,
Category = currentEntry.Category,
Type = currentEntry.EntryType,
InstanceID = currentEntry.InstanceId,
User = currentEntry.UserName,
};
lock (translatedLogs)
{
translatedLogs.Add(translatedEntry);
}
}
});
stopwatch.Stop();
Console.WriteLine("{0} logs were translated in {1} using backward loop.", translatedLogs.Count, stopwatch.Elapsed);
}
두 번째 (앞으로) 루프는 인덱스 0에서 시작하여 인덱스를 증가시킵니다.
static void Main(string[] args)
{
TranslateLogsUsingForwardLoop();
Console.WriteLine();
Thread.Sleep(2000);
TranslateLogsUsingBackwardLoop();
Console.ReadLine();
}
이것은 내가 무엇을 얻을 것입니다 (이 테스트를 수행 여러 번, 결과는 거의 동일) :
이private static void TranslateLogsUsingForwardLoop()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var originalLogs = EventLog.GetEventLogs();
var translatedLogs = new List<EventLogItem>();
Parallel.ForEach<EventLog>(originalLogs, currentLog =>
{
for (int index = 0; index < currentLog.Entries.Count; index++)
{
var currentEntry = currentLog.Entries[index];
EventLogItem translatedEntry = new EventLogItem
{
MachineName = currentEntry.MachineName,
LogName = currentLog.LogDisplayName,
CreatedTime = currentEntry.TimeGenerated,
Source = currentEntry.Source,
Message = currentEntry.Message,
Number = currentEntry.Index,
Category = currentEntry.Category,
Type = currentEntry.EntryType,
InstanceID = currentEntry.InstanceId,
User = currentEntry.UserName,
};
lock (translatedLogs)
{
translatedLogs.Add(translatedEntry);
}
}
});
stopwatch.Stop();
Console.WriteLine("{0} logs were translated in {1} using forward loop.", translatedLogs.Count, stopwatch.Elapsed);
}
그리고 주요 방법 :이 방법은 다음과 같이 정의된다
내가 테스트 한 서버가 매초마다 이벤트 로그에 기록되므로 번역 된 로그 수가 동일하지 않습니다. 그렇다면 왜 후진 루프가 더 빠릅니까? 처음에는 역 루프 알고리즘에서 currentLog.Entries.Count
이 단지 한 번만 평가 되었기 때문에 앞으로 루프에서 계산되고 모든 루프 반복에서 index
과 비교되어야하지만 다시 올바른 것으로 보이지 않기 때문에 처음에는 생각했습니다. 어떤 아이디어?
두 의견 :-) 옛날에 사용되는 방법을 예측할 수 있습니다. 타이밍에 항상 번인 루프가 포함됩니다. 프로세서가 예열되도록 (올바르게 조절) 타이밍을 시작하기 전에 일부 작업을 수행하십시오. 그리고'For' 루프 바로 전에 타이머를 시작하고 할당 연산자를 시간을 재는 것이 좋습니다. – ja72
테스트에 몇 개의 항목이 있습니까? 또한 정기적 인 (순차적 인) 루프로 시도해 보셨습니까? – ja72