在 C++ 中将变量转换和写入文件的最佳方式(性能驱动)是什么?
What is the best way (performance driven) to convert and write variables to a file in c++?
我想将这样的内容写入文件:
0x050 addik r13, r0, 4496
0x054 addik r2, r0, 2224
0x058 addik r1, r0, 7536
0x05c brlid r15, 200
...
以此类推...它是一个程序指令跟踪,将有数千行。
我正在读取 'elf' 解码指令,创建对象,设置其地址、指令、名称和寄存器参数,然后以上述格式将其写入文件。
在 speed/performance 中进行测量的最佳方法是什么?
现在我有了这个(仍然只是十六进制),我不知道这是否是继续编写我的代码的最佳方式:
转换函数:
static std::string toHex(const T &i) {
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
return stream.str();
};
写作:
while((newInstruction = manager->newInstruction())){
stream << Utils::toHex(newInstruction->getAddress())
<< " "
<< Utils::toHex(newInstruction->getInstruction())
<< endl;
trace->writeFile(stream.str());
stream.str(std::string());
}
编辑:
所以我根据答案得出了一个更快的解决方案。
我实施了 Escualo 给出的解决方案,在每次读取新指令时停止创建对象。
然后我阅读了 Thomas Matthews 给出的答案并让我想到不要在每次读取指令时都写入我的文件,因此 stringstream 现在就像一个大小为 1024 的缓冲区,当它超过然后该值将流写入文件:
while((newInstruction = manager->newInstruction())){
stream << myHex<unsigned int> << newInstruction->getAddress() << ' '
<< myHex<uint32_t> << newInstruction->getInstruction();
if(stream.tellp() > 1024){
trace->writeFile(stream.str());
stream.str(std::string());
}
}
首先,我会避免在每次调用格式化函数时创建和销毁 std::stringstream
。
回想一下,I/O 操纵器只不过是 return 流本身的函数。例如,一个操纵器完全按照您上面的指示执行操作,但不求助于临时 std::stringstream
可能看起来像:
#include <iostream>
#include <iomanip>
template<typename T,
typename CharT,
typename Traits = std::char_traits<CharT> >
inline std::basic_ostream<CharT, Traits>&
myhex(std::basic_ostream<CharT, Traits>& os) {
return os << "0x"
<< std::setfill('0')
<< std::setw(2 * sizeof(T))
<< std::hex;
}
int main() {
int x;
std::cout << myhex<int> << &x << std::endl;
}
打印(例如):
0x0x7fff5926cf9c
澄清一下:我不知道你为什么选择填充、宽度、前缀和格式;我只是向您展示如何创建一个不需要创建和销毁临时对象的 I/O 操纵器。
请注意,操纵器将适用于任何 std::basic_ostream<CharT, Traits>
,例如 std::cout
、std::cerr
、std::ofstream
和 std::stringstream
。
由于文件I/O比格式化的时间慢,我建议格式化到缓冲区,块将缓冲区写入文件。
char text_buffer[1024];
unsigned int bytes_formatted = 0;
for (unsigned int i = 0; i < 10; ++i)
{
int chars_formatted = snprintf(&text_buffer[bytes_formatted],
1024-bytes_formatted,
"hello %d", i);
if (chars_formatted > 0)
{
bytes_formatted += chars_formatted;
}
}
my_file.write(text_buffer, bytes_formatted);
大多数文件 I/O 操作的开销是恒定的,与操作无关。所以一次操作可以写入的数据越多越好。
我想将这样的内容写入文件:
0x050 addik r13, r0, 4496
0x054 addik r2, r0, 2224
0x058 addik r1, r0, 7536
0x05c brlid r15, 200
...
以此类推...它是一个程序指令跟踪,将有数千行。
我正在读取 'elf' 解码指令,创建对象,设置其地址、指令、名称和寄存器参数,然后以上述格式将其写入文件。
在 speed/performance 中进行测量的最佳方法是什么?
现在我有了这个(仍然只是十六进制),我不知道这是否是继续编写我的代码的最佳方式:
转换函数:
static std::string toHex(const T &i) {
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
return stream.str();
};
写作:
while((newInstruction = manager->newInstruction())){
stream << Utils::toHex(newInstruction->getAddress())
<< " "
<< Utils::toHex(newInstruction->getInstruction())
<< endl;
trace->writeFile(stream.str());
stream.str(std::string());
}
编辑:
所以我根据答案得出了一个更快的解决方案。
我实施了 Escualo 给出的解决方案,在每次读取新指令时停止创建对象。
然后我阅读了 Thomas Matthews 给出的答案并让我想到不要在每次读取指令时都写入我的文件,因此 stringstream 现在就像一个大小为 1024 的缓冲区,当它超过然后该值将流写入文件:
while((newInstruction = manager->newInstruction())){
stream << myHex<unsigned int> << newInstruction->getAddress() << ' '
<< myHex<uint32_t> << newInstruction->getInstruction();
if(stream.tellp() > 1024){
trace->writeFile(stream.str());
stream.str(std::string());
}
}
首先,我会避免在每次调用格式化函数时创建和销毁 std::stringstream
。
回想一下,I/O 操纵器只不过是 return 流本身的函数。例如,一个操纵器完全按照您上面的指示执行操作,但不求助于临时 std::stringstream
可能看起来像:
#include <iostream>
#include <iomanip>
template<typename T,
typename CharT,
typename Traits = std::char_traits<CharT> >
inline std::basic_ostream<CharT, Traits>&
myhex(std::basic_ostream<CharT, Traits>& os) {
return os << "0x"
<< std::setfill('0')
<< std::setw(2 * sizeof(T))
<< std::hex;
}
int main() {
int x;
std::cout << myhex<int> << &x << std::endl;
}
打印(例如):
0x0x7fff5926cf9c
澄清一下:我不知道你为什么选择填充、宽度、前缀和格式;我只是向您展示如何创建一个不需要创建和销毁临时对象的 I/O 操纵器。
请注意,操纵器将适用于任何 std::basic_ostream<CharT, Traits>
,例如 std::cout
、std::cerr
、std::ofstream
和 std::stringstream
。
由于文件I/O比格式化的时间慢,我建议格式化到缓冲区,块将缓冲区写入文件。
char text_buffer[1024];
unsigned int bytes_formatted = 0;
for (unsigned int i = 0; i < 10; ++i)
{
int chars_formatted = snprintf(&text_buffer[bytes_formatted],
1024-bytes_formatted,
"hello %d", i);
if (chars_formatted > 0)
{
bytes_formatted += chars_formatted;
}
}
my_file.write(text_buffer, bytes_formatted);
大多数文件 I/O 操作的开销是恒定的,与操作无关。所以一次操作可以写入的数据越多越好。