CComSafeArray 到制表符分隔值的速度改进建议
CComSafeArray to Tab-Separated Values Suggestions for Speed Improvement
我需要将 2D CComSafe 数组转换为制表符分隔值文本流。该数组可以包含任意数量的值,可能以数百万计。
相关代码块如下。
我强烈怀疑 generate_response_from_data 函数只是一种生成输出的残忍方式。但是我还没有找到更好方法的具体示例。是的,我已尽我所能进行搜索。
我试图弄清楚 Boost Karma 是否是更好的解决方案,但坦率地说,我只是不知道如何将它应用到我的用例中。
有人可以提供一些关于更快方法的意见吗?
// This is a 2D CComSafeArray
template<typename T>
class MyDataArray : public CComSafeArray<T>
{
public:
MyDataArray() : CComSafeArray<T>() {}
const T* get_value_ptr(long row, long col) const // 0-based indices.
{
// To shave off a tiny bit of time, validity of m_psa, row, and col are assumed.
// Not great but for our application, those are checked prior to call.
return &static_cast<T*>(this->m_psa->pvData)[this->m_psa->rgsabound[1].cElements * col + row];
}
// Other stuff for this class.
};
inline std::string my_variant_to_string(const VARIANT* p_var)
{
// Will only ever have VT_I4, VT_R8, VT_BSTR
if (VT_I4 == p_var->vt)
return boost::lexical_cast<std::string>(p_var->intVal); // Boost faster than other methods!!!
if (VT_R8 == p_var->vt)
return boost::lexical_cast<std::string>(p_var->dblVal); // Boost faster than other methods!!!
if (VT_BSTR == p_var->vt)
{
std::wstring wstr(p_var->bstrVal, SysStringLen(p_var->bstrVal));
return Utils::from_wide(wstr); // from_wide is a conversion function I created.
}
//if (VT_EMPTY == == p_var->vt) {} // Technically not needed.
return "";
}
template<typename T>
bool generate_response_from_data(const MyDataArray<T>& data_array, std::stringstream& response_body)
{
if (2 != data_array.GetDimensions())
return false;
long row_begin = data_array.GetLowerBound(0);
long row_end = data_array.GetUpperBound(0);
long col_begin = data_array.GetLowerBound(1);
long col_end = data_array.GetUpperBound(1);
if (row_end < row_begin || col_end < col_begin)
return false;
for (long r = row_begin; r <= row_end; ++r)
{
for (long c = col_begin; c <= col_end; ++c)
{
if (c > 0)
response_body << '\t';
response_body << my_variant_to_string(data_array.get_value_ptr(r, c));
}
response_body << '\n';
}
return true;
}
谢谢@MichaelGunter。您建议超载 << 会导致速度提高约 60%!我为每个值从 wstring 转换,因为与数值相比,字符串值的百分比相当小(如果有的话),并且在大多数情况下转换整个流可能是一种浪费。
已编辑以反映使用自定义函数从 BSTR 到 std::string 的直接转换。
std::stringstream& operator<<(std::stringstream& s, const VARIANT* p_v)
{
if (VT_I4 == p_v->vt)
s << p_v->intVal;
else if (VT_R8 == p_v->vt)
s << p_v->dblVal;
else if (VT_BSTR == p_v->vt)
{
//std::wstring wstr(p_v->bstrVal, SysStringLen(p_v->bstrVal));
s << Utils::from_bstr(p_v->bstrVal);
}
return s;
}
...
response_body << odata_array.get_value_ptr(r, c);
我需要将 2D CComSafe 数组转换为制表符分隔值文本流。该数组可以包含任意数量的值,可能以数百万计。
相关代码块如下。
我强烈怀疑 generate_response_from_data 函数只是一种生成输出的残忍方式。但是我还没有找到更好方法的具体示例。是的,我已尽我所能进行搜索。
我试图弄清楚 Boost Karma 是否是更好的解决方案,但坦率地说,我只是不知道如何将它应用到我的用例中。
有人可以提供一些关于更快方法的意见吗?
// This is a 2D CComSafeArray
template<typename T>
class MyDataArray : public CComSafeArray<T>
{
public:
MyDataArray() : CComSafeArray<T>() {}
const T* get_value_ptr(long row, long col) const // 0-based indices.
{
// To shave off a tiny bit of time, validity of m_psa, row, and col are assumed.
// Not great but for our application, those are checked prior to call.
return &static_cast<T*>(this->m_psa->pvData)[this->m_psa->rgsabound[1].cElements * col + row];
}
// Other stuff for this class.
};
inline std::string my_variant_to_string(const VARIANT* p_var)
{
// Will only ever have VT_I4, VT_R8, VT_BSTR
if (VT_I4 == p_var->vt)
return boost::lexical_cast<std::string>(p_var->intVal); // Boost faster than other methods!!!
if (VT_R8 == p_var->vt)
return boost::lexical_cast<std::string>(p_var->dblVal); // Boost faster than other methods!!!
if (VT_BSTR == p_var->vt)
{
std::wstring wstr(p_var->bstrVal, SysStringLen(p_var->bstrVal));
return Utils::from_wide(wstr); // from_wide is a conversion function I created.
}
//if (VT_EMPTY == == p_var->vt) {} // Technically not needed.
return "";
}
template<typename T>
bool generate_response_from_data(const MyDataArray<T>& data_array, std::stringstream& response_body)
{
if (2 != data_array.GetDimensions())
return false;
long row_begin = data_array.GetLowerBound(0);
long row_end = data_array.GetUpperBound(0);
long col_begin = data_array.GetLowerBound(1);
long col_end = data_array.GetUpperBound(1);
if (row_end < row_begin || col_end < col_begin)
return false;
for (long r = row_begin; r <= row_end; ++r)
{
for (long c = col_begin; c <= col_end; ++c)
{
if (c > 0)
response_body << '\t';
response_body << my_variant_to_string(data_array.get_value_ptr(r, c));
}
response_body << '\n';
}
return true;
}
谢谢@MichaelGunter。您建议超载 << 会导致速度提高约 60%!我为每个值从 wstring 转换,因为与数值相比,字符串值的百分比相当小(如果有的话),并且在大多数情况下转换整个流可能是一种浪费。
已编辑以反映使用自定义函数从 BSTR 到 std::string 的直接转换。
std::stringstream& operator<<(std::stringstream& s, const VARIANT* p_v)
{
if (VT_I4 == p_v->vt)
s << p_v->intVal;
else if (VT_R8 == p_v->vt)
s << p_v->dblVal;
else if (VT_BSTR == p_v->vt)
{
//std::wstring wstr(p_v->bstrVal, SysStringLen(p_v->bstrVal));
s << Utils::from_bstr(p_v->bstrVal);
}
return s;
}
...
response_body << odata_array.get_value_ptr(r, c);