В настоящее время я оцениваю использование ADO.NET для приложения C ++, которое в настоящее время использует обычный старый ADO. Учитывая, что мы переделываем все взаимодействие с базами данных, мы хотели бы определить, будет ли выгодным использование более современной и активно развивающейся технологии ADO.NET.
После некоторых измерений выясняется, что для определенных тестовых запросов, которые извлекают много строк с несколькими столбцами, которые все содержат строки, ADO.NET фактически на 20% медленнее для нас, чем обычный ADO. Наш профилировщик предполагает, что преобразование результатов System.String в std :: wstring, используемое приложением, является одним из узких мест. Я не могу переключить ни один из верхних уровней приложения на использование System.String, поэтому мы застряли с этим конкретным преобразованием.
Грубый набросок кода выглядит так:
System::Data::SqlClient::SqlCommand^ sqlCmd =
gcnew System::Data::SqlClient::SqlCommand(cmd, m_DBConnection.get());
System::Data::SqlClient::SqlDataReader^ reader = sqlCmd->ExecuteReader();
if (reader->HasRows)
{
using namespace msclr::interop;
while (reader->Read())
{
std::vector<std::wstring> results;
for (int i=0; i < reader->FieldCount; ++i)
{
std::wstring col_data;
TypeCode type = Type::GetTypeCode(reader->GetFieldType(i));
switch (type)
{
// ... omit lots of different types
case TypeCode::String:
{
System::String^ tmp = reader->GetString(i);
col_data = marshal_as<std::wstring>(tmp);
}
break;
// ... more type conversion code removed
}
results.push_back(col_data);
}
// NOTE: Callback into native result processing code
ResultsCallback(results);
}
Я потратил много времени на чтение различных способов получения std::wstring
из System.String и измерил большинство из них. Кажется, что все они работают примерно одинаково - мы говорим о десятичных точках в процентах загрузки процессора. В конце концов, я просто согласился использовать marshal_as<std::wstring>
, так как он наиболее читабелен и, по-видимому, так же эффективен, как и другие решения (то есть, используя PtrToStringChars
или метод, описанный в MSDN здесь ).
Использование DataReader работает очень хорошо с концептуальной точки зрения, так как большая часть обработки данных в любом случае ориентирована на строки.
Единственное другое немного неожиданное узкое место, которое я заметил, - это получение TypeCode
для столбцов результатов; Я уже планирую переместить это за пределы основного цикла обработки результатов и получать коды типов только один раз для каждого результата запроса.
После этого длительного введения кто-нибудь может порекомендовать менее дорогой способ преобразования строковых данных из System.String
в std::wstring
или я уже смотрю на оптимальную производительность здесь? Я, очевидно, больше ищу немного необычных способов, учитывая, что я уже попробовал все обычные ...
РЕДАКТИРОВАТЬ : Похоже, я попал в ловушку моего собственного изготовления здесь. Да, приведенный выше код примерно на 20% медленнее, чем эквивалентный простой код ADO в режиме Debug . Однако, переключая его в режим Release , узкое место все еще можно измерить, но приведенный выше код ADO.NET внезапно почти на 50% быстрее, чем старый код ADO. Так что, хотя меня все еще немного беспокоит стоимость преобразования строк, в режиме Release она не так велика, как это впервые показалось.