2008-09-22 11 views
4

Вот код, который я хочу ускорить. Он получает значение из набора записей ADO и преобразует его в char *. Но это медленно. Могу ли я пропустить создание _bstr_t?Получение символа * из _variant_t в оптимальное время

   _variant_t var = pRs->Fields->GetItem(i)->GetValue(); 

       if (V_VT(&var) == VT_BSTR) 
       { 
        char* p = (const char*) (_bstr_t) var; 
+0

Я бы рекомендовал сделать некоторые тайминги с предложенными здесь методами для подтверждения. Использовать QueryPerformanceCounter и QueryPerformanceFrequency API – PiNoYBoY82 2008-09-23 00:40:21

ответ

3

Первые 4 байта BSTR содержит длину. Вы можете выполнить цикл и получить каждый другой символ, если unicode или каждый символ, если он многобайт. Будет работать какой-то memcpy или другой метод. IIRC, это может быть быстрее, чем W2A или литья (LPCSTR)(_bstr_t)

2

Это создает временный в стеке:

USES_CONVERSION; 
char *p=W2A(var.bstrVal); 

Это использует немного более новый синтаксис и, вероятно, более надежным. Он имеет настраиваемый размер, за которым он будет использовать кучу, так что позволяет избежать ввода массивных строк в стеке:

char *p=CW2AEX<>(var.bstrVal); 
+0

Ну, мне понравился этот подход в теории, за исключением того, что это не очень быстро в соответствии с моими таймингами. – 2008-09-22 22:25:08

+0

Я удивлен, что это не так. Ваш оригинальный метод требует создания дополнительного BSTR, который должен проходить через распределитель COM. Оба мои просто копируют в буфер в стек с преобразованием. Если ваша исходная строка достаточно длинная, накладные расходы от конверсии, вероятно, являются наиболее значимыми. – 2008-09-22 22:28:48

+0

Мои строки короткие, но у меня их около 150 000 тысяч.То есть я перебираю строки и столбцы набора записей ADO, преобразуя BSTR в char * s, а затем нажимаю char * s на std :: vector из std :: strings. Занимает 3,2 секунды в обоих направлениях. – 2008-09-22 22:39:37

3

Вашей проблема (кроме возможности копии памяти внутри _bstr_t) является то, что вы конвертируете UNICODE BSTR в ANSI char *.

Вы можете использовать макросы USES_CONVERSION, которые выполняют преобразование в стеке, поэтому они могут быть быстрее. В качестве альтернативы, сохраните значение BSTR как unicode, если это возможно.

конвертировать:

USES_CONVERSION; 
char* p = strdup(OLE2A(var.bstrVal)); 

// ... 

free(p); 

запомнить - строка, возвращенная из OLE2A (и его сестра макросы) возвращает строку, которая выделяется в стеке - возврат из области видимости, и вы должны мусора строку, если не копировать это (и, бесплатно, в конце концов, очевидно)

-2

Хорошо, мой C++ становится немного ржавым ... но я не думаю, что преобразование - это ваша проблема. Это преобразование действительно не делает ничего, кроме указания компилятору рассмотреть _bstr_t char *. Затем вы просто назначаете адрес этого указателя на p. Ничего на самом деле «сделано».

Вы уверены, что это не просто медленное получение материала от GetValue?

Или мой C++ rustier, чем я думаю ...

0
_variant_t var = pRs->Fields->GetItem(i)->GetValue(); 

Вы также можете сделать это задание быстрее, избегая сбора полей все вместе. Вы должны использовать коллекцию Fields только тогда, когда вам нужно получить элемент по имени. Если вы знаете поля по индексу, вы можете использовать это.

_variant_t vara = pRs->Collect[i]->Value; 

Примечание я не могу быть целым числом, как ADO не поддерживает VT_INTEGER, так что вы можете также использовать длинную переменный.