在c ++中将变量转换和写入文件的最佳方法(性能驱动)是什么?

时间:2015-07-10 17:46:36

标签: c++ fstream sstream

我想把这样的东西写成文件:

0x050 addik r13, r0, 4496
0x054 addik r2, r0, 2224
0x058 addik r1, r0, 7536
0x05c brlid r15, 200
...

依此类推......它的程序指令跟踪将有数千行。

我正在阅读解释指令的'elf',创建一个对象,设置其地址,指令,名称和寄存器参数,然后以上述格式将其写入文件。

这是衡量速度/性能的最佳方法吗?

现在我有了这个(仍然只是十六进制),我不知道这是否是继续编写代码的最佳方式:

转换功能:

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());
    }
}

2 个答案:

答案 0 :(得分:1)

由于文件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操作都有一个恒定的开销。因此,在一次操作中可以写入的数据越多越好。

答案 1 :(得分:0)

首先,我会避免为每次调用格式化函数创建和销毁std::stringstream

回想一下,I / O操纵器只不过是返回流本身的函数。例如,一个操纵者完全按照上面的说明进行操作,但不使用临时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::coutstd::cerrstd::ofstreamstd::stringstream