Поправки к статье «Сравнение скорости доступа к данным (ADO.NET, ADO, ascDB)»
К сожалению, при тестировании средств доступа к базам данных (ADO.Net, ADO, ascDB) в одном из тестов были допущены несколько ошибок. После исправления ошибок оказалось необходимым внести некоторые корректировки в результаты тестирования, приведенные в предыдущей статье. Я приношу читателям свои извинения, каюсь и надеюсь, что подобного более не повторится.
Кроме упомянутых выше, есть и ещё одна причина, из-за которой я возвращаюсь к старой теме. Дело в том, что разработчикам удалось существенно ускорить ascDB в самом узком месте, а именно снизить время сохранения данных после их изменения примерно в полтора раза.
К сожалению, повторить старые условия тестирования не представилось возможным, поскольку изменились конфигурации машин, участвующих в тесте (в том числе изменились операционные системы, установленные на них).
Естественно, что, учитывая ошибки и изменение конфигурации, бессмысленно сравнивать новые данные со старыми. Однако, все описания тестов и выводы, сделанные в предыдущей статье, остаются в силе, за исключением изменений, описанных ниже. Так уж получилось, что результаты неверных тестов оказались недалеки от истины. :)
Описание изменений, произошедших в коде теста ChangeData
Где же были допущены ошибки и как они сказались на результатах тестирования? Все ошибки, коварно маскируясь во мраке кода, закрались в тест ChangeData.
Первая, самая непростительная и существенная из ошибок, "поразила" область выполнения операции Update, бесчестно сведя к минимуму количество реально выполняемых изменений данных в строках курсора. В коде теста после каждого вызова метода CursorUpdate находился лишний, вероятно, забытый в результате многочисленных правок, вызов метода CursorFetchRandom. Ниже приведен фрагмент кода с ошибкой (переменная curs представляет собой ascVisualCursor (ascDB), Recordset (ADO) или DataSet (ADO.Net)):
Понятно, что в этом случае на клиенте выполнялось 10 модификаций одной и той же строки, но на сервере операция Update выполнялась только один раз для одной строки вместо изменения значений в десяти строках. Правильный код выглядит так:
Исправление этой ошибки привело к изменению результатов теста ChangeData. Это произошло за счёт увеличения времени записи изменений для всех тестируемых средств доступа к базам данных.
Вторая ошибка заключалась в том, что в тесте ChangeData для ADO в методах CursorInsert, CursorDelete и CursorUpdate при нахождении курсора в состоянии EOF вызывался метод MovePrevious объекта Recordset. Это могло привести к значительным потерям времени в случае, когда курсор не был отключен от базы данных (из-за крайне медленной работы навигации по курсору ADO в connected-режиме).
Реорганизация теста позволила избежать ситуации EOF, в результате чего время выполнения операций Update и Delete в тесте ADO (connected-режим) очень сильно сократилось. Про операцию Insert сказано ниже (в описании третьей ошибки).
Третья и, надеюсь, последняя ошибка относилась только к методу CursorInsert теста ChangeData для ADO. Случайным и невероятным образом из кода этого метода исчезла крайне необходимая строка «ars.AddNew» (в которой ars является объектом Recordset), что неизбежно привело в полному отсутствию реальных вставок строк в тесте.
После добавления исчезнувшей строки время выполнения операции Insert (в тесте ChangeData для ADO), разумеется, возросло.
Описание изменений, произошедших в коде теста Forward
Изменения в тесте Forward коснулись только ADO.NET.
В результате внимательного рассмотрения проблемы больших затрат времени на выполнение метода Close объектов SqlDataReader и OleDbDataReader оказалось, что при попытке закрыть Reader выполняется докачка всех еще не считанных записей. Чтобы избежать этой неприятности при переоткрытии объекта в случае циклического повторения теста, были внесены изменения в код метода CloseReader тестового приложения. В старом коде выполнялось простое закрытие объекта SqlDataReader:
В новом коде дополнительно вызывается метод Cancel команды (объекта SqlCommand или OleDbCommand, в зависимости от определения #define CompileWithSqlClient или CompileWithOleDb):
После вызова метода Cancel команды, Reader закрывается намного быстрее. Однако появились проблемы. Иногда после этой операции в SQL-сервере появлялись блокировки, которые приводили к зависанию теста (с выдачей таймаута).
Новые результаты теста ChangeData
Анализируя новые результаты тестов, необходимо учитывать, что, помимо исправления ошибок, произошли следующие изменения.
В качестве клиентской машины во всех случаях использовался компьютер со следующими параметрами:
- ОС: Microsoft Windows XP Professional (Version 5.1.2600)
- P-III 800 Mhz
- RAM 384 Мб
- Page File 1 Гб
В качестве серверной машины в случае удаленных тестов использовался компьютер со следующими параметрами:
- ОС: Microsoft Windows XP Professional (Version 5.1.2600, Service Pack 1)
- Athlon Xp 2100+ (1733 МГц)
- RAM 512 Мб
- Page File 1.5 Мб
Тестовые приложения и библиотеки ADO.NET скомпилированы на C# из поставки Microsoft Development Environment 2003 Beta (Version 7.1.2292), Microsoft .Net Framework 1.1 (Version 1.1.4322).
Сам тест ChangeData был несколько реорганизован (увеличилось количество вызовов метода CursorFetch), увеличилось и количество вызовов методов CursorInsert и CursorUpdate.
Также нельзя забывать, что скорость записи изменений в курсоре ascDB была существенно увеличена разработчиками. Поэтому, несмотря на увеличение количества измененных строк, произошедшее в результате исправления ошибок, время записи изменений в ascDB сократилось почти вдвое. Дальнейшее ускорение работы ascDB представляется маловероятным по той причине, что ascDB поддерживает механизм триггеров, который в текущей версии невозможно отключить. Данные перед любой модификацией извлекаются из БД и передаются в триггерные события. К тому же модификация данных производится с помощью курсоров, что на некоторых СУБД дает дополнительные задержки.
Ниже приведены новые результаты тестов.
ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopen Количество повторов операции11501100115039301010 Таблица 1. Общее количество операций по 10 итерациям теста ChangeData (одинаково для всех тестов)
ChangeData (10 итераций)InProcess ClientCOM+ ClientNet RemotingClientCOM+ ServerNet Remoting Server ADO.NET21.17250.24267.775205.957194.74 ADO (в скобках – disconnected)39.156 (13.539)17.715нет33.808нет AscDB17.05518.177нет32.046нет Таблица 2. Результаты теста ChangeData
Как видно по таблице, общее время выполнения теста ADO.NET в удаленном режиме значительно меньше, чем время выполнения того же теста в соответствующих локальных режимах. Вероятнее всего, это связано с использованием в качестве клиента более быстрой машины с большим объемом оперативной памяти. В результате разница в скорости копирования данных при их десериализации на клиенте оказалась существенной, и даже передача данных по сети не смогла сгладить разницу. Подробнее о причинах медленной сериализации объекта DataSet было сказано в предыдущей статье. Единственное, что можно добавить – похоже, DataSet всегда сериализуется в XML. Однако вряд ли этим фактом можно объяснить столь медленную сериализацию.
ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего ADO.NET0.0200.0700.000.03014.1296.92121.170 ADO (connected)0.3100.1700.0229.9427.0301.67439.156 ADO (disconnected)0.3610.4810.070.6017.2094.81713.539 ascDB0.4610.6010.012.05310.6853.24517.055 Таблица 3. Результаты теста ChangeData по операциям. Режим in-process.
ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего ADO.NET0.080.1520.020.02021.682228.286250.240 ADO0.360.4510.080.6415.45810.72517.715 ascDB0.480.4710.022.84510.9653.39618.177 Таблица 4. Результаты теста ChangeData по операциям. Локальный режим через COM+
ChangeData (10 итераций)InsertUpdateDeleteFetchSaveReopenВсего ADO.NET0.040.040.010.00026.11179.757205.957 ADO0.110.170.000.2706.51026.74833.808 ascDB0.6530.170.0115.47911.7084.02632.046 Таблица 5. Результаты теста ChangeData по операциям. Удаленный режим через COM+
Коррекция выводов, сделанных в предыдущей статье
Преимущество ADO (disconnected-режим) над ascDB теперь представляется незначительным. Хотя нельзя забывать о том, что в disconnected-режиме ADO вынуждено передавать весь курсор на клиента, а ascDB – нет. Дело в том, что ascDB реализует полноценную докачку (поблочную) данных, что можно сравнить с обычным connected-режимом ADO. Однако, во-первых, в обычном режиме ADO показало намного худшие результаты, а во-вторых, disconnected-режим – единственный разумный режим для ADO, так как подключенный курсор в ADO передается по ссылке, и любой вызов метода будет осуществляться по сети.
Неверным оказался вывод о низкой скорости выполнения операции Delete в ADO (connected-режим): в этом режиме тормозит только операция Fetch (т.е. Move метода Recordset).
Подтвердилось, что увеличение объема оперативной памяти сверх 256 Мб существенно ускоряет работу ADO.NET, тогда как для ADO и ascDB вполне достаточно 256 Мб (разумеется, речь идет о тесте ChangeData, так как остальные тесты не изменялись).
Прочие выводы остались без изменений.
Заключение
Я ещё раз приношу читателям искренние извинения за допущенные ошибки.
Возможно, памятуя о непростительности ошибок в подобных тестах, автору следовало бы совершить ритуальное самоубийство, но надеюсь, что отсутствие среди предков автора самураев позволяет мне сохранить себе жизнь и рассчитывать в дальнейшем на прощение читательской аудиторией :-).