字符串操作性能问题
String manipulation performance problems
最近,我们遇到了一段生成XML的代码的性能问题。想在这里分享经验。这有点长,请耐心等待。
我们准备了一个包含许多项的简单XML。每个项目可以有5-10个元素。结构是这样的:
<Root>
<Item>
<Element1Key>Element1Val</Element1Key>
<Element2Key>Element2Val</Element2Key>
<Element3Key>Element3Val</Element3Key>
<Element4Key>Element4Val</Element4Key>
<Element5Key>Element5Val</Element5Key>
<Item>
<Item>
<Element1Key>Element1Val</Element1Key>
<Element2Key>Element2Val</Element2Key>
<Element3Key>Element3Val</Element3Key>
<Element4Key>Element4Val</Element4Key>
<Element5Key>Element5Val</Element5Key>
<Item>
</Root>
生成XML的代码是(以全局函数的简化形式):
void addElement(std::string& aStr_inout, const std::string& aKey_in, const std::string& aValue_in)
{
aStr_inout += "<";
aStr_inout += aKey_in;
aStr_inout += ">";
aStr_inout += "Elemem1Val";
aStr_inout += "<";
aStr_inout += aValue_in;
aStr_inout += ">";
}
void PrepareXML_Original()
{
clock_t commence,complete;
commence=clock();
std::string anXMLString;
anXMLString += "<Root>";
for(int i = 0; i < 200; i++)
{
anXMLString += "<Item>";
addElement(anXMLString, "Elemem1Key", "Elemem1Value");
addElement(anXMLString, "Elemem2Key", "Elemem2Value");
addElement(anXMLString, "Elemem3Key", "Elemem3Value");
addElement(anXMLString, "Elemem4Key", "Elemem4Value");
addElement(anXMLString, "Elemem5Key", "Elemem5Value");
anXMLString += "</Item>";
replaceAll(anXMLString, "&", "&");
replaceAll(anXMLString, "'", "'");
replaceAll(anXMLString, """, """);
replaceAll(anXMLString, "<", "<");
replaceAll(anXMLString, ">", ">");
}
anXMLString += "</Root>";
complete=clock();
LONG lTime=(complete-commence);
std::cout << "Time taken for the operation is :"<< lTime << std::endl;
}
replaceAll()代码将用编码的形式替换特殊字符。如下所示。
void replaceAll(std::string& str, const std::string& from, const std::string& to)
{
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
在最小的例子中,我已经编码了200个项目。但是,在实际情况下,情况可能会更糟。上面的代码花了大约20秒创建XML。这远远超出了任何可接受的限度。可能是什么问题?如何提高这里的性能?
注意:字符串类的用法没有太大区别。我用MFC CString的另一个字符串实现测试了相同的逻辑,得到了类似的(更糟糕的)观察结果。此外,我不想在这里使用任何DOM XML解析器来更好地准备XML。这个问题并不是XML特有的。
如果您可以在创建内容之前估计结果字符串(anXMLString
)的长度,那么您可以为字符串分配足够的缓冲空间。当缓冲区足够大时,就不会重新分配和复制(目标字符串)。
这样:
std::string anXMLString;
anXMLString.reserve( size );
我不确定std::string,它是否需要搜索附加点,或者是否在内存中保持字符串的长度。
我意识到问题可能是由于同一个字符串越来越长,结果如下:1.随着字符串的增长,字符串连接变得更加昂贵2.随着循环的进行,字符替换发生在较大的字符串中,并且速度越来越慢。
为了解决这个问题,我使用了一个临时字符串来对单个项目进行XML编码,在循环结束时,我将这个小XML附加到主XML中。修改后的方法如下。
for(int i = 0; i < 200; i++)
{
std::string anItemString; // Create a new string for the individual Item entry
anItemString += "<Item>";
addElement(anItemString, "Elemem1Key", "Elemem1Value");
addElement(anItemString, "Elemem2Key", "Elemem2Value");
addElement(anItemString, "Elemem3Key", "Elemem3Value");
addElement(anItemString, "Elemem4Key", "Elemem4Value");
addElement(anItemString, "Elemem5Key", "Elemem5Value");
anItemString += "</Item>";
replaceAll(anItemString, "&", "&");
replaceAll(anItemString, "'", "'");
replaceAll(anItemString, """, """);
replaceAll(anItemString, "<", "<");
replaceAll(anItemString, ">", ">");
anXMLString += anItemString; // Do all the operations on the new string and finally append to the main string.
}
这提高了XML创建的性能,所花费的时间仅为17毫秒!
因此,我学到的教训是,当创建更大的结果时,将其拆分为子运算,将子运算的结果收集到新的字符串中,并向全局结果追加一次。我不确定这是否已经是一个模式或名称。
由于StackOverFlow提供了在问答方面分享经验的选项;A、 我想利用它。欢迎任何意见/改进。
- 在类中使用随机生成器时出现性能问题
- Qt OpenGL 渲染到纹理性能问题
- 剪辑性能问题
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- OpenCV - 基本操作 - 性能问题 [模式:发布]
- 使用 #define 进行跟踪日志记录以避免性能问题
- 在 Qt C++ 中在自定义项委托上绘制文本时的性能问题
- std::函数有性能问题,如何避免?
- 使用 const double* const 作为模板参数 - 代码性能问题
- 在C 中读取大型CSV文件性能问题
- MPI 二进制文件 I/O 基本功能和性能问题
- 如何修复macOS线程互斥锁性能缓慢的问题?
- 使用STD :: MAP在数据及其性能问题中查找重复项.我可以预先分配吗?
- C 功能性能问题
- 一维数组映射方式的性能差异问题
- 在C 性能问题中使用Getter返回地图
- 初始化每个班级成员时的性能问题
- 事件(开始,结束),1天的最大事件.C++ 中的性能问题
- 在X64模式下从C /CLI调用MASM PROC会产生意外的性能问题
- OpenGL:MESA3D屏幕上的软件渲染性能问题