From dc01c490203f770fea468338b52a740f8eb83d71 Mon Sep 17 00:00:00 2001 From: Victor Zarubkin Date: Sun, 2 Oct 2016 12:13:12 +0300 Subject: [PATCH] Saving network data using temporary cache file + Question box when clicked on "Clear all" --- include/profiler/reader.h | 57 ++---- profiler_gui/main_window.cpp | 112 +++++++----- profiler_gui/main_window.h | 17 +- reader/main.cpp | 6 +- src/reader.cpp | 331 ++++++----------------------------- 5 files changed, 149 insertions(+), 374 deletions(-) diff --git a/include/profiler/reader.h b/include/profiler/reader.h index 8c4c643..1134ff6 100644 --- a/include/profiler/reader.h +++ b/include/profiler/reader.h @@ -78,7 +78,6 @@ namespace profiler { public: typedef ::std::vector blocks_t; - typedef ::std::vector pblocks_t; typedef ::std::vector<::profiler::block_index_t> children_t; children_t children; ///< List of children blocks. May be empty. @@ -235,7 +234,6 @@ namespace profiler { }; // END of class BlocksTreeRoot. typedef ::profiler::BlocksTree::blocks_t blocks_t; - typedef ::profiler::BlocksTree::pblocks_t pblocks_t; typedef ::std::unordered_map<::profiler::thread_id_t, ::profiler::BlocksTreeRoot, ::profiler::passthrough_hash> thread_blocks_tree_t; ////////////////////////////////////////////////////////////////////////// @@ -383,18 +381,22 @@ namespace profiler { extern "C" { PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic& progress, const char* filename, - ::profiler::FileData& filedata, + ::profiler::SerializedData& serialized_blocks, + ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& threaded_trees, + uint32_t& total_descriptors_number, bool gather_statistics, ::std::stringstream& _log); PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic& progress, ::std::stringstream& str, - ::profiler::FileData& filedata, + ::profiler::SerializedData& serialized_blocks, + ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& threaded_trees, + uint32_t& total_descriptors_number, bool gather_statistics, ::std::stringstream& _log); @@ -402,31 +404,18 @@ extern "C" { ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::std::stringstream& _log); - - PROFILER_API bool writeTreesToStream(::std::atomic& progress, - ::std::stringstream& str, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log); - - PROFILER_API bool writeTreesToFile(::std::atomic& progress, - const char* filename, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log); } -inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::FileData& filedata, +inline ::profiler::block_index_t fillTreesFromFile(const char* filename, ::profiler::SerializedData& serialized_blocks, + ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& _blocks, - ::profiler::thread_blocks_tree_t& threaded_trees, bool gather_statistics, + ::profiler::thread_blocks_tree_t& threaded_trees, + uint32_t& total_descriptors_number, + bool gather_statistics, ::std::stringstream& _log) { ::std::atomic progress = ATOMIC_VAR_INIT(0); - return fillTreesFromFile(progress, filename, filedata, descriptors, _blocks, threaded_trees, gather_statistics, _log); + return fillTreesFromFile(progress, filename, serialized_blocks, serialized_descriptors, descriptors, _blocks, threaded_trees, total_descriptors_number, gather_statistics, _log); } inline bool readDescriptionsFromStream(::std::stringstream& str, @@ -438,28 +427,6 @@ inline bool readDescriptionsFromStream(::std::stringstream& str, return readDescriptionsFromStream(progress, str, serialized_descriptors, descriptors, _log); } -inline bool writeTreesToStream(::std::stringstream& str, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log) -{ - ::std::atomic progress = ATOMIC_VAR_INIT(0); - return writeTreesToStream(progress, str, filedata, threaded_trees, _descriptors, _blocks, _log); -} - -inline bool writeTreesToFile(const char* filename, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log) -{ - ::std::atomic progress = ATOMIC_VAR_INIT(0); - return writeTreesToFile(progress, filename, filedata, threaded_trees, _descriptors, _blocks, _log); -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif // PROFILER_READER____H diff --git a/profiler_gui/main_window.cpp b/profiler_gui/main_window.cpp index 521b909..d621c21 100644 --- a/profiler_gui/main_window.cpp +++ b/profiler_gui/main_window.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include "main_window.h" #include "blocks_tree_widget.h" @@ -79,6 +80,7 @@ ////////////////////////////////////////////////////////////////////////// const int LOADER_TIMER_INTERVAL = 40; +const auto NETWORK_CACHE_FILE = "easy_profiler_stream.cache"; ////////////////////////////////////////////////////////////////////////// @@ -376,7 +378,7 @@ void EasyMainWindow::onReloadFileClicked(bool) void EasyMainWindow::onSaveFileClicked(bool) { - if (m_filedata.serialized_blocks.empty()) + if (m_serializedBlocks.empty()) return; const auto i = m_lastFile.lastIndexOf(QChar('/')); @@ -390,26 +392,30 @@ void EasyMainWindow::onSaveFileClicked(bool) auto filename = QFileDialog::getSaveFileName(this, "Save profiler log", dir, "Profiler Log File (*.prof);;All Files (*.*)"); if (!filename.isEmpty()) { - QMessageBox::warning(this, "Warning", "Saving is not working yet :)", QMessageBox::Close); - - /* - ::std::stringstream errorMessage; - - ::profiler::pblocks_t blocks(EASY_GLOBALS.gui_blocks.size()); - for (size_t i = 0, size = EASY_GLOBALS.gui_blocks.size(); i < size; ++i) - blocks[i] = &EASY_GLOBALS.gui_blocks[i].tree; - - if (writeTreesToFile(filename.toStdString().c_str(), m_filedata, EASY_GLOBALS.profiler_blocks, EASY_GLOBALS.descriptors, blocks, errorMessage)) + auto result = QFile::copy(m_bNetworkFileRegime ? QString(NETWORK_CACHE_FILE) : m_lastFile, filename); + if (result) + { m_lastFile = filename; + if (m_bNetworkFileRegime) + { + m_bNetworkFileRegime = false; + QFile::remove(NETWORK_CACHE_FILE); + } + } + else if (m_bNetworkFileRegime) + { + QMessageBox::warning(this, "Warning", "Can not save network cahce to file.\nSaving incomplete.", QMessageBox::Close); + } else - QMessageBox::warning(this, "Warning", QString("Can not save blocks to file.\n\nReason:\n%1").arg(errorMessage.str().c_str()), QMessageBox::Close); - */ + { + QMessageBox::warning(this, "Warning", "Can not copy last file.\nSaving incomplete.", QMessageBox::Close); + } } } ////////////////////////////////////////////////////////////////////////// -void EasyMainWindow::onDeleteClicked(bool) +void EasyMainWindow::clear() { static_cast(m_treeWidget->widget())->clearSilent(true); static_cast(m_graphicsView->widget())->clear(); @@ -426,11 +432,20 @@ void EasyMainWindow::onDeleteClicked(bool) EASY_GLOBALS.descriptors.clear(); EASY_GLOBALS.gui_blocks.clear(); - m_filedata.serialized_blocks.clear(); - m_filedata.serialized_descriptors.clear(); + m_serializedBlocks.clear(); + m_serializedDescriptors.clear(); m_saveAction->setEnabled(false); m_deleteAction->setEnabled(false); + + m_bNetworkFileRegime = false; +} + +void EasyMainWindow::onDeleteClicked(bool) +{ + auto button = QMessageBox::question(this, "Clear all profiled data", "All profiled data is going to be deleted!\nContinue?", QMessageBox::Yes, QMessageBox::No); + if (button == QMessageBox::Yes) + clear(); } ////////////////////////////////////////////////////////////////////////// @@ -758,12 +773,14 @@ void EasyMainWindow::onFileReaderTimeout() { static_cast(m_treeWidget->widget())->clearSilent(true); - ::profiler::FileData fd; + ::profiler::SerializedData serialized_blocks; + ::profiler::SerializedData serialized_descriptors; ::profiler::descriptors_list_t descriptors; ::profiler::blocks_t blocks; ::profiler::thread_blocks_tree_t threads_map; QString filename; - m_reader.get(fd, descriptors, blocks, threads_map, filename); + uint32_t descriptorsNumberInFile = 0; + m_reader.get(serialized_blocks, serialized_descriptors, descriptors, blocks, threads_map, descriptorsNumberInFile, filename); if (threads_map.size() > 0xff) { @@ -774,9 +791,12 @@ void EasyMainWindow::onFileReaderTimeout() qWarning() << "Warning: Currently, maximum number of displayed threads is 255! Some threads will not be displayed."; } - if (m_reader.isFile()) + m_bNetworkFileRegime = !m_reader.isFile(); + if (!m_bNetworkFileRegime) m_lastFile = ::std::move(filename); - m_filedata = ::std::move(fd); + m_serializedBlocks = ::std::move(serialized_blocks); + m_serializedDescriptors = ::std::move(serialized_descriptors); + m_descriptorsNumberInFile = descriptorsNumberInFile; EASY_GLOBALS.selected_thread = 0; ::profiler_gui::set_max(EASY_GLOBALS.selected_block); EASY_GLOBALS.profiler_blocks.swap(threads_map); @@ -876,7 +896,8 @@ void EasyFileReader::load(const QString& _filename) m_isFile = true; m_filename = _filename; m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { - m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_filedata, m_descriptors, m_blocks, m_blocksTree, _enableStatistics, m_errorMessage), ::std::memory_order_release); + m_size.store(fillTreesFromFile(m_progress, m_filename.toStdString().c_str(), m_serializedBlocks, m_serializedDescriptors, + m_descriptors, m_blocks, m_blocksTree, m_descriptorsNumberInFile, _enableStatistics, m_errorMessage), ::std::memory_order_release); m_progress.store(100, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release); }, EASY_GLOBALS.enable_statistics)); @@ -890,7 +911,13 @@ void EasyFileReader::load(::std::stringstream& _stream) m_filename.clear(); m_stream.swap(_stream); m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { - m_size.store(fillTreesFromStream(m_progress, m_stream, m_filedata, m_descriptors, m_blocks, m_blocksTree, _enableStatistics, m_errorMessage), ::std::memory_order_release); + ::std::ofstream cache_file(NETWORK_CACHE_FILE, ::std::fstream::binary); + if (cache_file.is_open()) { + cache_file << m_stream.str(); + cache_file.close(); + } + m_size.store(fillTreesFromStream(m_progress, m_stream, m_serializedBlocks, m_serializedDescriptors, m_descriptors, + m_blocks, m_blocksTree, m_descriptorsNumberInFile, _enableStatistics, m_errorMessage), ::std::memory_order_release); m_progress.store(100, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release); }, EASY_GLOBALS.enable_statistics)); @@ -905,33 +932,30 @@ void EasyFileReader::interrupt() m_bDone.store(false, ::std::memory_order_release); m_progress.store(0, ::std::memory_order_release); m_size.store(0, ::std::memory_order_release); - m_filedata.serialized_blocks.clear(); - m_filedata.serialized_descriptors.clear(); + m_serializedBlocks.clear(); + m_serializedDescriptors.clear(); m_descriptors.clear(); m_blocks.clear(); m_blocksTree.clear(); + m_descriptorsNumberInFile = 0; { decltype(m_stream) dummy; dummy.swap(m_stream); } { decltype(m_errorMessage) dummy; dummy.swap(m_errorMessage); } } -void EasyFileReader::get(::profiler::FileData& _filedata, ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, - ::profiler::thread_blocks_tree_t& _tree, QString& _filename) +void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors, + ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, + ::profiler::thread_blocks_tree_t& _tree, uint32_t& _descriptorsNumberInFile, QString& _filename) { if (done()) { - m_filedata.serialized_blocks.swap(_filedata.serialized_blocks); - m_filedata.serialized_descriptors.swap(_filedata.serialized_descriptors); - m_filedata.threads_order.swap(_filedata.threads_order); + m_serializedBlocks.swap(_serializedBlocks); + m_serializedDescriptors.swap(_serializedDescriptors); ::profiler::descriptors_list_t(::std::move(m_descriptors)).swap(_descriptors); m_blocks.swap(_blocks); m_blocksTree.swap(_tree); m_filename.swap(_filename); - _filedata.cpu_frequency = m_filedata.cpu_frequency; - _filedata.begin_time = m_filedata.begin_time; - _filedata.end_time = m_filedata.end_time; - _filedata.total_blocks_number = m_filedata.total_blocks_number; - _filedata.total_descriptors_number = m_filedata.total_descriptors_number; + _descriptorsNumberInFile = m_descriptorsNumberInFile; } } @@ -1071,34 +1095,34 @@ void EasyMainWindow::onGetBlockDescriptionsClicked(bool) { // Read descriptions from stream decltype(EASY_GLOBALS.descriptors) descriptors; - decltype(m_filedata.serialized_descriptors) serializedDescriptors; + decltype(m_serializedDescriptors) serializedDescriptors; ::std::stringstream errorMessage; if (readDescriptionsFromStream(m_listener.data(), serializedDescriptors, descriptors, errorMessage)) { bool cancel = false; - const bool doFlush = m_filedata.total_descriptors_number != descriptors.size(); - if (doFlush && !m_filedata.serialized_blocks.empty()) + const bool doFlush = m_descriptorsNumberInFile != descriptors.size(); + if (doFlush && !m_serializedBlocks.empty()) { auto button = QMessageBox::question(this, "Information", QString("New blocks description number = %1\ndiffers from the old one = %2.\nTo avoid possible conflicts\nall profiled data will be deleted.\nPress \"Yes\" to continue or \"No\" to cancel.") .arg(descriptors.size()) - .arg(m_filedata.total_descriptors_number), + .arg(m_descriptorsNumberInFile), QMessageBox::Yes, QMessageBox::No); if (button == QMessageBox::Yes) - onDeleteClicked(true); // Clear all contents because new descriptors list conflicts with old one + clear(); // Clear all contents because new descriptors list conflicts with old one else cancel = true; } if (!cancel) { - auto oldnumber = m_filedata.total_descriptors_number; - m_filedata.total_descriptors_number = static_cast(descriptors.size()); + auto oldnumber = m_descriptorsNumberInFile; + m_descriptorsNumberInFile = static_cast(descriptors.size()); EASY_GLOBALS.descriptors.swap(descriptors); - m_filedata.serialized_descriptors.swap(serializedDescriptors); + m_serializedDescriptors.swap(serializedDescriptors); - if (!doFlush && !m_filedata.serialized_blocks.empty() && descriptors.size() > oldnumber) + if (!doFlush && !m_serializedBlocks.empty() && descriptors.size() > oldnumber) { // There are dynamically added descriptors, add them to the new list too @@ -1120,7 +1144,7 @@ void EasyMainWindow::onGetBlockDescriptionsClicked(bool) if (desc != nullptr) { QMessageBox::warning(this, "Warning", "Conflict with dynamically added block descriptions.\nAll profiled data will be cleared.", QMessageBox::Close); - onDeleteClicked(true); + clear(); cancel = true; break; } diff --git a/profiler_gui/main_window.h b/profiler_gui/main_window.h index aa4c99e..ceab11b 100644 --- a/profiler_gui/main_window.h +++ b/profiler_gui/main_window.h @@ -61,13 +61,15 @@ namespace profiler { namespace net { struct EasyProfilerStatus; } } class EasyFileReader Q_DECL_FINAL { - ::profiler::FileData m_filedata; ///< + ::profiler::SerializedData m_serializedBlocks; ///< + ::profiler::SerializedData m_serializedDescriptors; ///< ::profiler::descriptors_list_t m_descriptors; ///< ::profiler::blocks_t m_blocks; ///< ::profiler::thread_blocks_tree_t m_blocksTree; ///< ::std::stringstream m_stream; ///< ::std::stringstream m_errorMessage; ///< QString m_filename; ///< + uint32_t m_descriptorsNumberInFile = 0; ///< ::std::thread m_thread; ///< ::std::atomic_bool m_bDone; ///< ::std::atomic m_progress; ///< @@ -88,9 +90,9 @@ public: void load(const QString& _filename); void load(::std::stringstream& _stream); void interrupt(); - void get(::profiler::FileData& _filedata, ::profiler::descriptors_list_t& _descriptors, - ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree, - QString& _filename); + void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors, + ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree, + uint32_t& _descriptorsNumberInFile, QString& _filename); QString getError(); @@ -171,7 +173,8 @@ protected: class QMessageBox* m_listenerDialog = nullptr; QTimer m_readerTimer; QTimer m_listenerTimer; - ::profiler::FileData m_filedata; + ::profiler::SerializedData m_serializedBlocks; + ::profiler::SerializedData m_serializedDescriptors; EasyFileReader m_reader; EasySocketListener m_listener; @@ -186,7 +189,9 @@ protected: class QAction* m_eventTracingEnableAction = nullptr; class QAction* m_eventTracingPriorityAction = nullptr; + uint32_t m_descriptorsNumberInFile = 0; uint16_t m_lastPort = 0; + bool m_bNetworkFileRegime = false; public: @@ -233,6 +238,8 @@ private: // Private non-virtual methods + void clear(); + void loadFile(const QString& filename); void readStream(::std::stringstream& data); diff --git a/reader/main.cpp b/reader/main.cpp index f894cb0..d2b4dc3 100644 --- a/reader/main.cpp +++ b/reader/main.cpp @@ -110,11 +110,13 @@ int main(int argc, char* argv[]) auto start = std::chrono::system_clock::now(); - ::profiler::FileData fd; + ::profiler::SerializedData serialized_blocks, serialized_descriptors; ::profiler::descriptors_list_t descriptors; ::profiler::blocks_t blocks; ::std::stringstream errorMessage; - auto blocks_counter = fillTreesFromFile(filename.c_str(), fd, descriptors, blocks, threaded_trees, true, errorMessage); + uint32_t descriptorsNumberInFile = 0; + auto blocks_counter = fillTreesFromFile(filename.c_str(), serialized_blocks, serialized_descriptors, descriptors, blocks, + threaded_trees, descriptorsNumberInFile, true, errorMessage); if (blocks_counter == 0) std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str(); diff --git a/src/reader.cpp b/src/reader.cpp index ea3d725..d22a153 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -252,84 +252,15 @@ void validate_pointers(::std::atomic& _progress, const char* _oldbase, ::pr ////////////////////////////////////////////////////////////////////////// -uint64_t write_block_recursive(float& _progress, float _prog_per_block, ::std::vector& _buf, ::std::stringstream& _stream, const ::profiler::FileData& _filedata, const ::profiler::BlocksTree& _tree, const ::profiler::pblocks_t& _blocks, const ::profiler::descriptors_list_t& _descriptors) -{ - uint64_t total_size = 0; - for (const auto chld : _tree.children) - total_size += write_block_recursive(_progress, _prog_per_block, _buf, _stream, _filedata, *_blocks[chld], _blocks, _descriptors); - - auto sz = static_cast(sizeof(::profiler::SerializedBlock) + strlen(_tree.node->name()) + 1); - - _buf.resize(sz); - memcpy(_buf.data(), _tree.node->data(), sz); - - auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(_buf.data()); - auto t_end = t_begin + 1; - - *t_begin *= _filedata.cpu_frequency; - *t_begin /= TIME_FACTOR; - *t_end *= _filedata.cpu_frequency; - *t_end /= TIME_FACTOR; - - if (_tree.node->id() >= _filedata.total_descriptors_number) - { - auto desc = _descriptors[_tree.node->id()]; - for (uint32_t i = 0; i < _filedata.total_descriptors_number; ++i) - { - if (_descriptors[i] == desc) - { - reinterpret_cast<::profiler::SerializedBlock*>(_buf.data())->setId(i); - break; - } - } - } - - write(_stream, sz); - write(_stream, _buf.data(), sz); - total_size += sz; - - _progress += _prog_per_block; - - return total_size; -} - -uint64_t write_block_recursive(float& _progress, float _prog_per_block, ::std::vector& _buf, ::std::stringstream& _stream, const ::profiler::FileData& _filedata, const ::profiler::BlocksTree& _tree, const ::profiler::pblocks_t& _blocks) -{ - uint64_t total_size = 0; - for (const auto chld : _tree.children) - total_size += write_block_recursive(_progress, _prog_per_block, _buf, _stream, _filedata, *_blocks[chld], _blocks); - - auto sz = static_cast(sizeof(::profiler::SerializedBlock) + strlen(_tree.node->name()) + 1); - - _buf.resize(sz); - memcpy(_buf.data(), _tree.node->data(), sz); - - auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(_buf.data()); - auto t_end = t_begin + 1; - - *t_begin *= _filedata.cpu_frequency; - *t_begin /= TIME_FACTOR; - *t_end *= _filedata.cpu_frequency; - *t_end /= TIME_FACTOR; - - write(_stream, sz); - write(_stream, _buf.data(), sz); - total_size += sz; - - _progress += _prog_per_block; - - return total_size; -} - -////////////////////////////////////////////////////////////////////////// - extern "C" { PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic& progress, const char* filename, - ::profiler::FileData& filedata, + ::profiler::SerializedData& serialized_blocks, + ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& blocks, ::profiler::thread_blocks_tree_t& threaded_trees, + uint32_t& total_descriptors_number, bool gather_statistics, ::std::stringstream& _log) { @@ -353,7 +284,8 @@ extern "C" { stringstream_parent& s = str; auto oldbuf = s.rdbuf(inFile.rdbuf()); - auto result = fillTreesFromStream(progress, str, filedata, descriptors, blocks, threaded_trees, gather_statistics, _log); + auto result = fillTreesFromStream(progress, str, serialized_blocks, serialized_descriptors, descriptors, blocks, + threaded_trees, total_descriptors_number, gather_statistics, _log); s.rdbuf(oldbuf); return result; @@ -362,10 +294,12 @@ extern "C" { ////////////////////////////////////////////////////////////////////////// PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic& progress, ::std::stringstream& inFile, - ::profiler::FileData& filedata, + ::profiler::SerializedData& serialized_blocks, + ::profiler::SerializedData& serialized_descriptors, ::profiler::descriptors_list_t& descriptors, ::profiler::blocks_t& blocks, ::profiler::thread_blocks_tree_t& threaded_trees, + uint32_t& total_descriptors_number, bool gather_statistics, ::std::stringstream& _log) { @@ -394,24 +328,24 @@ extern "C" { return 0; } - filedata.cpu_frequency = 0LL; - inFile.read((char*)&filedata.cpu_frequency, sizeof(int64_t)); + int64_t cpu_frequency = 0LL; + inFile.read((char*)&cpu_frequency, sizeof(int64_t)); - filedata.begin_time = 0; - filedata.end_time = 0; - inFile.read((char*)&filedata.begin_time, sizeof(::profiler::timestamp_t)); - inFile.read((char*)&filedata.end_time, sizeof(::profiler::timestamp_t)); - if (filedata.cpu_frequency != 0) + ::profiler::timestamp_t begin_time = 0ULL; + ::profiler::timestamp_t end_time = 0ULL; + inFile.read((char*)&begin_time, sizeof(::profiler::timestamp_t)); + inFile.read((char*)&end_time, sizeof(::profiler::timestamp_t)); + if (cpu_frequency != 0) { - filedata.begin_time *= TIME_FACTOR; - filedata.begin_time /= filedata.cpu_frequency; - filedata.end_time *= TIME_FACTOR; - filedata.end_time /= filedata.cpu_frequency; + begin_time *= TIME_FACTOR; + begin_time /= cpu_frequency; + end_time *= TIME_FACTOR; + end_time /= cpu_frequency; } - filedata.total_blocks_number = 0; - inFile.read((char*)&filedata.total_blocks_number, sizeof(decltype(filedata.total_blocks_number))); - if (filedata.total_blocks_number == 0) + uint32_t total_blocks_number = 0; + inFile.read((char*)&total_blocks_number, sizeof(uint32_t)); + if (total_blocks_number == 0) { _log << "Profiled blocks number == 0"; return 0; @@ -421,13 +355,13 @@ extern "C" { inFile.read((char*)&memory_size, sizeof(decltype(memory_size))); if (memory_size == 0) { - _log << "Wrong memory size == 0 for " << filedata.total_blocks_number << " blocks"; + _log << "Wrong memory size == 0 for " << total_blocks_number << " blocks"; return 0; } - filedata.total_descriptors_number = 0; - inFile.read((char*)&filedata.total_descriptors_number, sizeof(decltype(filedata.total_descriptors_number))); - if (filedata.total_descriptors_number == 0) + total_descriptors_number = 0; + inFile.read((char*)&total_descriptors_number, sizeof(uint32_t)); + if (total_descriptors_number == 0) { _log << "Blocks description number == 0"; return 0; @@ -437,17 +371,17 @@ extern "C" { inFile.read((char*)&descriptors_memory_size, sizeof(decltype(descriptors_memory_size))); if (descriptors_memory_size == 0) { - _log << "Wrong memory size == 0 for " << filedata.total_descriptors_number << " blocks descriptions"; + _log << "Wrong memory size == 0 for " << total_descriptors_number << " blocks descriptions"; return 0; } - descriptors.reserve(filedata.total_descriptors_number); - //const char* olddata = append_regime ? filedata.serialized_descriptors.data() : nullptr; - filedata.serialized_descriptors.set(descriptors_memory_size); - //validate_pointers(progress, olddata, filedata.serialized_descriptors, descriptors, descriptors.size()); + descriptors.reserve(total_descriptors_number); + //const char* olddata = append_regime ? serialized_descriptors.data() : nullptr; + serialized_descriptors.set(descriptors_memory_size); + //validate_pointers(progress, olddata, serialized_descriptors, descriptors, descriptors.size()); uint64_t i = 0; - while (!inFile.eof() && descriptors.size() < filedata.total_descriptors_number) + while (!inFile.eof() && descriptors.size() < total_descriptors_number) { uint16_t sz = 0; inFile.read((char*)&sz, sizeof(sz)); @@ -462,7 +396,7 @@ extern "C" { // return 0; //} - char* data = filedata.serialized_descriptors[i]; + char* data = serialized_descriptors[i]; inFile.read(data, sz); auto descriptor = reinterpret_cast<::profiler::SerializedBlockDescriptor*>(data); descriptors.push_back(descriptor); @@ -480,16 +414,16 @@ extern "C" { PerThreadStats thread_statistics, parent_statistics, frame_statistics; IdMap identification_table; - blocks.reserve(filedata.total_blocks_number); - //olddata = append_regime ? filedata.serialized_blocks.data() : nullptr; - filedata.serialized_blocks.set(memory_size); - //validate_pointers(progress, olddata, filedata.serialized_blocks, blocks, blocks.size()); + blocks.reserve(total_blocks_number); + //olddata = append_regime ? serialized_blocks.data() : nullptr; + serialized_blocks.set(memory_size); + //validate_pointers(progress, olddata, serialized_blocks, blocks, blocks.size()); i = 0; uint32_t read_number = 0; ::profiler::block_index_t blocks_counter = 0; ::std::vector name; - while (!inFile.eof() && read_number < filedata.total_blocks_number) + while (!inFile.eof() && read_number < total_blocks_number) { EASY_BLOCK("Read thread data", ::profiler::colors::DarkGreen); @@ -497,7 +431,6 @@ extern "C" { inFile.read((char*)&thread_id, sizeof(decltype(thread_id))); auto& root = threaded_trees[thread_id]; - filedata.threads_order.push_back(thread_id); uint16_t name_size = 0; inFile.read((char*)&name_size, sizeof(uint16_t)); @@ -525,25 +458,25 @@ extern "C" { return 0; } - char* data = filedata.serialized_blocks[i]; + char* data = serialized_blocks[i]; inFile.read(data, sz); i += sz; auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); auto t_end = t_begin + 1; - if (filedata.cpu_frequency != 0) + if (cpu_frequency != 0) { *t_begin *= TIME_FACTOR; - *t_begin /= filedata.cpu_frequency; + *t_begin /= cpu_frequency; *t_end *= TIME_FACTOR; - *t_end /= filedata.cpu_frequency; + *t_end /= cpu_frequency; } - if (*t_end > filedata.begin_time) + if (*t_end > begin_time) { - if (*t_begin < filedata.begin_time) - *t_begin = filedata.begin_time; + if (*t_begin < begin_time) + *t_begin = begin_time; blocks.emplace_back(); ::profiler::BlocksTree& tree = blocks.back(); @@ -581,11 +514,11 @@ extern "C" { return 0; } - char* data = filedata.serialized_blocks[i]; + char* data = serialized_blocks[i]; inFile.read(data, sz); i += sz; auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); - if (baseData->id() >= filedata.total_descriptors_number) + if (baseData->id() >= total_descriptors_number) { _log << "Bad block id == " << baseData->id(); return 0; @@ -601,18 +534,18 @@ extern "C" { auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); auto t_end = t_begin + 1; - if (filedata.cpu_frequency != 0) + if (cpu_frequency != 0) { *t_begin *= TIME_FACTOR; - *t_begin /= filedata.cpu_frequency; + *t_begin /= cpu_frequency; *t_end *= TIME_FACTOR; - *t_end /= filedata.cpu_frequency; + *t_end /= cpu_frequency; } - if (*t_end >= filedata.begin_time) + if (*t_end >= begin_time) { - if (*t_begin < filedata.begin_time) - *t_begin = filedata.begin_time; + if (*t_begin < begin_time) + *t_begin = begin_time; blocks.emplace_back(); ::profiler::BlocksTree& tree = blocks.back(); @@ -889,162 +822,4 @@ extern "C" { ////////////////////////////////////////////////////////////////////////// - PROFILER_API bool writeTreesToFile(::std::atomic& progress, - const char* filename, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log) - { - ::std::ofstream of(filename, std::fstream::binary); - if (!of.is_open()) - { - _log << "Can not open file " << filename << " for writing"; - return false; - } - - ::std::stringstream str; - //typedef ::std::basic_iostream<::std::stringstream::char_type, ::std::stringstream::traits_type> stringstream_parent; - //stringstream_parent& s = str; - //auto oldbuf = s.rdbuf(of.rdbuf()); - - auto result = writeTreesToStream(progress, str, filedata, threaded_trees, _descriptors, _blocks, _log); - - of << str.str(); - //of.close(); - //s.rdbuf(oldbuf); - return result; - } - - PROFILER_API bool writeTreesToStream(::std::atomic& progress, - ::std::stringstream& str, - const ::profiler::FileData& filedata, - const ::profiler::thread_blocks_tree_t& threaded_trees, - const ::profiler::descriptors_list_t& _descriptors, - const ::profiler::pblocks_t& _blocks, - ::std::stringstream& _log) - { - auto oldprogress = progress.exchange(0, ::std::memory_order_release); - if (oldprogress < 0) - { - _log << "Writing was interrupted"; - return false; // Loading interrupted - } - - write(str, PROFILER_SIGNATURE); - write(str, ::profiler::EASY_FULL_VERSION); - write(str, filedata.cpu_frequency); - - decltype(filedata.begin_time) begin_time = filedata.begin_time; - begin_time *= filedata.cpu_frequency; - begin_time /= TIME_FACTOR; - write(str, begin_time); - - decltype(filedata.end_time) end_time = filedata.end_time; - end_time *= filedata.cpu_frequency; - end_time /= TIME_FACTOR; - write(str, end_time); - - write(str, filedata.total_blocks_number); - write(str, filedata.serialized_blocks.size()); - write(str, filedata.total_descriptors_number); - write(str, filedata.serialized_descriptors.size()); - - decltype(filedata.total_descriptors_number) n = 0; - uint64_t i = 0, size = filedata.serialized_descriptors.size(); - while (i < size) - { - const char* data = filedata.serialized_descriptors[i]; - auto descriptor = reinterpret_cast(data); - auto sz = static_cast(sizeof(::profiler::SerializedBlockDescriptor) + strlen(descriptor->name()) + strlen(descriptor->file()) + 2); - - write(str, sz); - write(str, data, sz); - ++n; - - i += sz; - - auto oldprogress = progress.exchange(static_cast(20 * i / filedata.serialized_descriptors.size()), ::std::memory_order_release); - if (oldprogress < 0) - { - _log << "Writing was interrupted"; - return false; // Loading interrupted - } - } - - if (n != filedata.total_descriptors_number || i != size) - printf("ERROR writing descriptors\n"); - - float prog = (float)progress.load(::std::memory_order_acquire); - if (prog < 0) - { - _log << "Writing was interrupted"; - return false; // Loading interrupted - } - - const float prog_per_thread = 80.f / (float)threaded_trees.size(); - - i = 0; - ::std::vector buffer; - for (auto tid : filedata.threads_order) - { - auto it = threaded_trees.find(tid); - if (it == threaded_trees.end()) - { - printf("Bad thread id = %u\n", tid); - continue; - } - - const auto& root = it->second; - - auto total = root.children.size() + root.sync.size(); - const float prog_per_block = total > 0 ? prog_per_thread / total : 0.f; - - write(str, root.thread_id); - - auto name_size = static_cast(strlen(root.name()) + 1); - const char* name = name_size > 1 ? root.name() : ""; - write(str, name_size); - write(str, name, name_size); - - auto blocks_number_in_thread = static_cast(root.sync.size()); - write(str, blocks_number_in_thread); - for (auto b : root.sync) - { - i += write_block_recursive(prog, prog_per_block, buffer, str, filedata, *_blocks[b], _blocks); - - auto oldprogress = progress.exchange(static_cast(prog), ::std::memory_order_release); - if (oldprogress < 0) - { - _log << "Writing was interrupted"; - return false; // Loading interrupted - } - } - - blocks_number_in_thread = static_cast(root.children.size()); - write(str, blocks_number_in_thread); - for (auto b : root.children) - { - i += write_block_recursive(prog, prog_per_block, buffer, str, filedata, *_blocks[b], _blocks, _descriptors); - - auto oldprogress = progress.exchange(static_cast(prog), ::std::memory_order_release); - if (oldprogress < 0) - { - _log << "Writing was interrupted"; - return false; // Loading interrupted - } - } - } - - if (i != filedata.serialized_blocks.size()) - printf("ERROR writing blocks\n"); - - printf("Finished writing to file\n"); - progress.store(100, ::std::memory_order_release); - return true; - } - - ////////////////////////////////////////////////////////////////////////// - }