2015-07-10 1 views
0

Я хочу написать что-то вроде этого в файл:Каков наилучший способ (производительность) для преобразования и записи переменных в файл в C++?

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

И так далее ... Его команда программы трассировки, которая будет иметь тысячи строк.

Я читаю от «эльфа», декодируя инструкцию, создавая объект, задавая его адрес, команду, имя и регистры, а затем записывая его в указанном выше формате в файл.

Что это лучший способ, измеряя скорость/производительность, чтобы это сделать?

Теперь у меня есть это (еще только шестнадцатиричном), и я не знаю, если это лучший способ, чтобы продолжить писать свой код:

Преобразование функции:

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

EDIT:

Так я достиг более быстрое решение, основанное на ответы.

Для одного я реализовал решение, заданное Escualo, чтобы прекратить создавать объекты каждый раз, когда я читаю новую инструкцию.

И затем я прочитал ответ, заданный Thomas Matthews, и дал мне идею не писать в мой файл при каждой прочитанной инструкции, поэтому строковый поток теперь работает как буфер с размером 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()); 
    } 
} 
+0

как 'writeFile()' закодирован? – NathanOliver

+2

Что делает скорость/производительность наиболее важным аспектом этого кода (а не читабельность, ремонтопригодность, повторное использование или другие приятные вещи)? Я спрашиваю, потому что, когда скорость _really_ важна, самый быстрый способ записи переменных в файл состоит в том, чтобы напрямую копировать байты (которые не читаются человеком) и запускать более медленную программу позже, когда время уже не самое главное, перевести их для удобочитаемого текста. –

+0

Проблема заключается в том, что ей придется управлять инструкциями по сборке из других программ, которые могут легко получить миллион инструкций, и я должен декодировать каждую инструкцию, которая требует времени, а затем обнаруживает последовательности, которые занимают еще больше времени, а затем пишут все, чтобы файлы. – joaomlap

ответ

0

с одной стороны, я бы не создавать и уничтожаем std::stringstream для каждого вызова вашей функции форматирования.

Напомним, что манипуляторы ввода-вывода - это не что иное, как функции, которые возвращают поток. Например, манипулятор делает именно то, что вы указали выше, но не прибегая к временному 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 

Для уточнения: я не знайте, почему вы выбираете заполнение, ширину, префикс и формат; Я просто показываю вам, как создать манипулятор ввода-вывода, который не влечет за собой создание и уничтожение временных объектов.

Обратите внимание, что манипулятор будет работать с любым std::basic_ostream<CharT, Traits>, такие как std::cout, std::cerr, std::ofstream и std::stringstream.

+0

Мне понравилась идея не создавать одноразовый объект каждый раз, когда я читал инструкцию, но я борюсь с решением, которое вы представили, так как я получаю эту компиляционную ошибку: 'main.cpp: 23: ошибка: аргументы шаблона по умолчанию могут не быть используется в шаблонах функций без -std = C++ 0x или -std = gnu ++ 0x make: *** [main.o] Ошибка 1 ' – joaomlap

+0

Итак, просто сделайте то, что говорит компилятор: add' -std = C++ 0x' в вашу строку компиляции (это говорит компилятору использовать стандарт C++ 11). – Escualo

+0

Я пробовал, и время работы, безусловно, уменьшилось. – joaomlap

1

Поскольку файловый ввод-вывод работает медленнее, чем время форматирования, я предлагаю форматирование в буфер, блок, записывающий буфер в файл.

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

Большинство операций ввода-вывода данных имеют постоянные накладные расходы, независимо от операции. Таким образом, чем больше данных, которые могут быть записаны за одну операцию, тем лучше.

Смежные вопросы