Выполнение тестов C # на производительность кода
Недавно я работал над проектом, в котором мне нужно было проанализировать XML-файлы размером от 5 до 20 МБ. Производительность была критически важна для проекта, поэтому я хотел убедиться, что проанализирую эти файлы как можно быстрее.
Мне известны два класса C # для синтаксического анализа XML: XmlReader
и XmlDocument
. Основываясь на моем понимании этих двух классов, XmlReader
должен работать быстрее в моем сценарии, потому что он читает XML-документ только один раз, никогда не сохраняя в памяти больше, чем текущий узел. Напротив, XmlDocument
сохраняет весь XML-файл в памяти, что снижает производительность.
Не зная наверняка, какой метод мне следует использовать, я решил написать быстрый тест производительности, чтобы измерить фактические результаты этих двух классов.
Данные
В своем проекте я заранее знал, какие данные мне нужно извлечь из XML, поэтому решил настроить тест таким образом, чтобы имитировать это требование. Если бы мой проект требовал, чтобы я запускал рекурсивную логику в XML-документе, нуждаясь в части информации ниже в XML, чтобы знать, какие части информации извлекать из XML раньше, я бы настроил совершенно другой тест.
Для своего теста я решил использовать дамп пользовательских данных Photography Stack Exchange в качестве образца файла, поскольку он имитирует структуру и размер файла данных одного из моих реальных проектов. Дампы данных Stack Exchange - отличные образцы наборов данных, потому что они включают реальные данные и выпускаются под лицензией Creative Commons.
Тест
Код C # для моего теста можно полностью найти на GitHub.
В своем тесте я создал два метода для извлечения одних и тех же точных данных из XML; один из методов использовался XmlReader
, а другой XmlDocument
.
В первом тесте используется XmlReader
. Объект XmlReader
сохраняет в памяти только один узел за раз, поэтому для чтения всего документа нам нужно использоватьwhile(reader.Read())
, чтобы зациклить все узлы. Внутри цикла мы проверяем, является ли каждый узел тем элементом, который мы ищем, и если да, то анализируем необходимые данные:
С другой стороны, код для XmlDocument
намного проще: мы загружаем весь XML-файл в память, а затем пишем LINQ-запрос, чтобы найти интересующие элементы:
После написания этих двух методов и подтверждения того, что они возвращают одинаковые точные результаты, пришло время сопоставить их друг с другом. Я написал метод, позволяющий запускать каждый из двух моих методов синтаксического анализа более 50 раз и брать среднее время выполнения каждого из них, чтобы исключить любые выбросы данных:
Результаты и выводы.
Переходя к делу, в моем тесте XmlReader
показал себя быстрее:
Значит ли разница в скорости ~ 0,14 секунды? В моем случае это так, потому что я буду анализировать гораздо больше элементов и файлов десятки раз в день. По моим оценкам, после выполнения математических расчетов я сэкономлю 45–60 секунд на синтаксическом анализе для каждого набора файлов XML, что очень много для системы, работающей почти в реальном времени.
Пришел бы я к такому же выводу, если бы молниеносная скорость не была одним из моих требований? Нет, я бы, вероятно, пошел по пути XmlDocument
, потому что код намного чище и, следовательно, его легче поддерживать.
А если бы мои файлы XML были размером 50, 500 или 5 ГБ? Я бы, вероятно, все еще использовал XmlReader
в этот момент, потому что попытка сохранить 5 ГБ данных в памяти будет не очень хорошо.
А как насчет сценария, когда мне нужно вернуться назад в моем XML-документе - это может быть тот случай, когда я бы использовал XmlDocument
, потому что с этим классом удобнее перемещаться вперед и назад. Однако гибридный подход может быть моим лучшим вариантом, если данные позволяют это: если я могу использовать XmlReader
, чтобы быстро просмотреть большую часть моего контента, а затем загрузить только определенные дочерние деревья элементов в XmlDocument
для облегчения обратного / прямого обхода, тогда это Казалось бы, идеальный сценарий.
Короче говоря, в моем сценарии XmlReader
был быстрее, чем XmlDocumet
. Единственный способ прийти к такому выводу - это провести несколько реальных тестов и измерить данные о производительности.
Итак, следует ли вам использовать XmlReader
или XmlDocument
в вашем следующем проекте? Ответ в зависимости от обстоятельств.