0
0
mirror of https://github.com/yse/easy_profiler.git synced 2024-12-27 08:41:02 +08:00

Saving network data using temporary cache file + Question box when clicked on "Clear all"

This commit is contained in:
Victor Zarubkin 2016-10-02 12:13:12 +03:00
parent 817083d3ff
commit dc01c49020
5 changed files with 149 additions and 374 deletions

View File

@ -78,7 +78,6 @@ namespace profiler {
public: public:
typedef ::std::vector<This> blocks_t; typedef ::std::vector<This> blocks_t;
typedef ::std::vector<This*> pblocks_t;
typedef ::std::vector<::profiler::block_index_t> children_t; typedef ::std::vector<::profiler::block_index_t> children_t;
children_t children; ///< List of children blocks. May be empty. children_t children; ///< List of children blocks. May be empty.
@ -235,7 +234,6 @@ namespace profiler {
}; // END of class BlocksTreeRoot. }; // END of class BlocksTreeRoot.
typedef ::profiler::BlocksTree::blocks_t blocks_t; 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; 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" { extern "C" {
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename, PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::FileData& filedata, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log); ::std::stringstream& _log);
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str, PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& str,
::profiler::FileData& filedata, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& _blocks, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log); ::std::stringstream& _log);
@ -402,31 +404,18 @@ extern "C" {
::profiler::SerializedData& serialized_descriptors, ::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::std::stringstream& _log); ::std::stringstream& _log);
PROFILER_API bool writeTreesToStream(::std::atomic<int>& 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<int>& 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::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::stringstream& _log)
{ {
::std::atomic<int> progress = ATOMIC_VAR_INIT(0); ::std::atomic<int> 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, inline bool readDescriptionsFromStream(::std::stringstream& str,
@ -438,28 +427,6 @@ inline bool readDescriptionsFromStream(::std::stringstream& str,
return readDescriptionsFromStream(progress, str, serialized_descriptors, descriptors, _log); 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<int> 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<int> progress = ATOMIC_VAR_INIT(0);
return writeTreesToFile(progress, filename, filedata, threaded_trees, _descriptors, _blocks, _log);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // PROFILER_READER____H #endif // PROFILER_READER____H

View File

@ -60,6 +60,7 @@
#include <QLabel> #include <QLabel>
#include <QDialog> #include <QDialog>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QFile>
#include "main_window.h" #include "main_window.h"
#include "blocks_tree_widget.h" #include "blocks_tree_widget.h"
@ -79,6 +80,7 @@
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
const int LOADER_TIMER_INTERVAL = 40; 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) void EasyMainWindow::onSaveFileClicked(bool)
{ {
if (m_filedata.serialized_blocks.empty()) if (m_serializedBlocks.empty())
return; return;
const auto i = m_lastFile.lastIndexOf(QChar('/')); 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 (*.*)"); auto filename = QFileDialog::getSaveFileName(this, "Save profiler log", dir, "Profiler Log File (*.prof);;All Files (*.*)");
if (!filename.isEmpty()) if (!filename.isEmpty())
{ {
QMessageBox::warning(this, "Warning", "Saving is not working yet :)", QMessageBox::Close); auto result = QFile::copy(m_bNetworkFileRegime ? QString(NETWORK_CACHE_FILE) : m_lastFile, filename);
if (result)
/* {
::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))
m_lastFile = filename; 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 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<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true); static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->clear(); static_cast<EasyGraphicsViewWidget*>(m_graphicsView->widget())->clear();
@ -426,11 +432,20 @@ void EasyMainWindow::onDeleteClicked(bool)
EASY_GLOBALS.descriptors.clear(); EASY_GLOBALS.descriptors.clear();
EASY_GLOBALS.gui_blocks.clear(); EASY_GLOBALS.gui_blocks.clear();
m_filedata.serialized_blocks.clear(); m_serializedBlocks.clear();
m_filedata.serialized_descriptors.clear(); m_serializedDescriptors.clear();
m_saveAction->setEnabled(false); m_saveAction->setEnabled(false);
m_deleteAction->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<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true); static_cast<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
::profiler::FileData fd; ::profiler::SerializedData serialized_blocks;
::profiler::SerializedData serialized_descriptors;
::profiler::descriptors_list_t descriptors; ::profiler::descriptors_list_t descriptors;
::profiler::blocks_t blocks; ::profiler::blocks_t blocks;
::profiler::thread_blocks_tree_t threads_map; ::profiler::thread_blocks_tree_t threads_map;
QString filename; 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) 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."; 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_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; EASY_GLOBALS.selected_thread = 0;
::profiler_gui::set_max(EASY_GLOBALS.selected_block); ::profiler_gui::set_max(EASY_GLOBALS.selected_block);
EASY_GLOBALS.profiler_blocks.swap(threads_map); EASY_GLOBALS.profiler_blocks.swap(threads_map);
@ -876,7 +896,8 @@ void EasyFileReader::load(const QString& _filename)
m_isFile = true; m_isFile = true;
m_filename = _filename; m_filename = _filename;
m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { 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_progress.store(100, ::std::memory_order_release);
m_bDone.store(true, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release);
}, EASY_GLOBALS.enable_statistics)); }, EASY_GLOBALS.enable_statistics));
@ -890,7 +911,13 @@ void EasyFileReader::load(::std::stringstream& _stream)
m_filename.clear(); m_filename.clear();
m_stream.swap(_stream); m_stream.swap(_stream);
m_thread = ::std::move(::std::thread([this](bool _enableStatistics) { 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_progress.store(100, ::std::memory_order_release);
m_bDone.store(true, ::std::memory_order_release); m_bDone.store(true, ::std::memory_order_release);
}, EASY_GLOBALS.enable_statistics)); }, EASY_GLOBALS.enable_statistics));
@ -905,33 +932,30 @@ void EasyFileReader::interrupt()
m_bDone.store(false, ::std::memory_order_release); m_bDone.store(false, ::std::memory_order_release);
m_progress.store(0, ::std::memory_order_release); m_progress.store(0, ::std::memory_order_release);
m_size.store(0, ::std::memory_order_release); m_size.store(0, ::std::memory_order_release);
m_filedata.serialized_blocks.clear(); m_serializedBlocks.clear();
m_filedata.serialized_descriptors.clear(); m_serializedDescriptors.clear();
m_descriptors.clear(); m_descriptors.clear();
m_blocks.clear(); m_blocks.clear();
m_blocksTree.clear(); m_blocksTree.clear();
m_descriptorsNumberInFile = 0;
{ decltype(m_stream) dummy; dummy.swap(m_stream); } { decltype(m_stream) dummy; dummy.swap(m_stream); }
{ decltype(m_errorMessage) dummy; dummy.swap(m_errorMessage); } { decltype(m_errorMessage) dummy; dummy.swap(m_errorMessage); }
} }
void EasyFileReader::get(::profiler::FileData& _filedata, ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, void EasyFileReader::get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::thread_blocks_tree_t& _tree, QString& _filename) ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks,
::profiler::thread_blocks_tree_t& _tree, uint32_t& _descriptorsNumberInFile, QString& _filename)
{ {
if (done()) if (done())
{ {
m_filedata.serialized_blocks.swap(_filedata.serialized_blocks); m_serializedBlocks.swap(_serializedBlocks);
m_filedata.serialized_descriptors.swap(_filedata.serialized_descriptors); m_serializedDescriptors.swap(_serializedDescriptors);
m_filedata.threads_order.swap(_filedata.threads_order);
::profiler::descriptors_list_t(::std::move(m_descriptors)).swap(_descriptors); ::profiler::descriptors_list_t(::std::move(m_descriptors)).swap(_descriptors);
m_blocks.swap(_blocks); m_blocks.swap(_blocks);
m_blocksTree.swap(_tree); m_blocksTree.swap(_tree);
m_filename.swap(_filename); m_filename.swap(_filename);
_filedata.cpu_frequency = m_filedata.cpu_frequency; _descriptorsNumberInFile = m_descriptorsNumberInFile;
_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;
} }
} }
@ -1071,34 +1095,34 @@ void EasyMainWindow::onGetBlockDescriptionsClicked(bool)
{ {
// Read descriptions from stream // Read descriptions from stream
decltype(EASY_GLOBALS.descriptors) descriptors; decltype(EASY_GLOBALS.descriptors) descriptors;
decltype(m_filedata.serialized_descriptors) serializedDescriptors; decltype(m_serializedDescriptors) serializedDescriptors;
::std::stringstream errorMessage; ::std::stringstream errorMessage;
if (readDescriptionsFromStream(m_listener.data(), serializedDescriptors, descriptors, errorMessage)) if (readDescriptionsFromStream(m_listener.data(), serializedDescriptors, descriptors, errorMessage))
{ {
bool cancel = false; bool cancel = false;
const bool doFlush = m_filedata.total_descriptors_number != descriptors.size(); const bool doFlush = m_descriptorsNumberInFile != descriptors.size();
if (doFlush && !m_filedata.serialized_blocks.empty()) if (doFlush && !m_serializedBlocks.empty())
{ {
auto button = QMessageBox::question(this, "Information", 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.") 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(descriptors.size())
.arg(m_filedata.total_descriptors_number), .arg(m_descriptorsNumberInFile),
QMessageBox::Yes, QMessageBox::No); QMessageBox::Yes, QMessageBox::No);
if (button == QMessageBox::Yes) 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 else
cancel = true; cancel = true;
} }
if (!cancel) if (!cancel)
{ {
auto oldnumber = m_filedata.total_descriptors_number; auto oldnumber = m_descriptorsNumberInFile;
m_filedata.total_descriptors_number = static_cast<uint32_t>(descriptors.size()); m_descriptorsNumberInFile = static_cast<uint32_t>(descriptors.size());
EASY_GLOBALS.descriptors.swap(descriptors); 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 // There are dynamically added descriptors, add them to the new list too
@ -1120,7 +1144,7 @@ void EasyMainWindow::onGetBlockDescriptionsClicked(bool)
if (desc != nullptr) if (desc != nullptr)
{ {
QMessageBox::warning(this, "Warning", "Conflict with dynamically added block descriptions.\nAll profiled data will be cleared.", QMessageBox::Close); QMessageBox::warning(this, "Warning", "Conflict with dynamically added block descriptions.\nAll profiled data will be cleared.", QMessageBox::Close);
onDeleteClicked(true); clear();
cancel = true; cancel = true;
break; break;
} }

View File

@ -61,13 +61,15 @@ namespace profiler { namespace net { struct EasyProfilerStatus; } }
class EasyFileReader Q_DECL_FINAL class EasyFileReader Q_DECL_FINAL
{ {
::profiler::FileData m_filedata; ///< ::profiler::SerializedData m_serializedBlocks; ///<
::profiler::SerializedData m_serializedDescriptors; ///<
::profiler::descriptors_list_t m_descriptors; ///< ::profiler::descriptors_list_t m_descriptors; ///<
::profiler::blocks_t m_blocks; ///< ::profiler::blocks_t m_blocks; ///<
::profiler::thread_blocks_tree_t m_blocksTree; ///< ::profiler::thread_blocks_tree_t m_blocksTree; ///<
::std::stringstream m_stream; ///< ::std::stringstream m_stream; ///<
::std::stringstream m_errorMessage; ///< ::std::stringstream m_errorMessage; ///<
QString m_filename; ///< QString m_filename; ///<
uint32_t m_descriptorsNumberInFile = 0; ///<
::std::thread m_thread; ///< ::std::thread m_thread; ///<
::std::atomic_bool m_bDone; ///< ::std::atomic_bool m_bDone; ///<
::std::atomic<int> m_progress; ///< ::std::atomic<int> m_progress; ///<
@ -88,9 +90,9 @@ public:
void load(const QString& _filename); void load(const QString& _filename);
void load(::std::stringstream& _stream); void load(::std::stringstream& _stream);
void interrupt(); void interrupt();
void get(::profiler::FileData& _filedata, ::profiler::descriptors_list_t& _descriptors, void get(::profiler::SerializedData& _serializedBlocks, ::profiler::SerializedData& _serializedDescriptors,
::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree, ::profiler::descriptors_list_t& _descriptors, ::profiler::blocks_t& _blocks, ::profiler::thread_blocks_tree_t& _tree,
QString& _filename); uint32_t& _descriptorsNumberInFile, QString& _filename);
QString getError(); QString getError();
@ -171,7 +173,8 @@ protected:
class QMessageBox* m_listenerDialog = nullptr; class QMessageBox* m_listenerDialog = nullptr;
QTimer m_readerTimer; QTimer m_readerTimer;
QTimer m_listenerTimer; QTimer m_listenerTimer;
::profiler::FileData m_filedata; ::profiler::SerializedData m_serializedBlocks;
::profiler::SerializedData m_serializedDescriptors;
EasyFileReader m_reader; EasyFileReader m_reader;
EasySocketListener m_listener; EasySocketListener m_listener;
@ -186,7 +189,9 @@ protected:
class QAction* m_eventTracingEnableAction = nullptr; class QAction* m_eventTracingEnableAction = nullptr;
class QAction* m_eventTracingPriorityAction = nullptr; class QAction* m_eventTracingPriorityAction = nullptr;
uint32_t m_descriptorsNumberInFile = 0;
uint16_t m_lastPort = 0; uint16_t m_lastPort = 0;
bool m_bNetworkFileRegime = false;
public: public:
@ -233,6 +238,8 @@ private:
// Private non-virtual methods // Private non-virtual methods
void clear();
void loadFile(const QString& filename); void loadFile(const QString& filename);
void readStream(::std::stringstream& data); void readStream(::std::stringstream& data);

View File

@ -110,11 +110,13 @@ int main(int argc, char* argv[])
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
::profiler::FileData fd; ::profiler::SerializedData serialized_blocks, serialized_descriptors;
::profiler::descriptors_list_t descriptors; ::profiler::descriptors_list_t descriptors;
::profiler::blocks_t blocks; ::profiler::blocks_t blocks;
::std::stringstream errorMessage; ::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) if (blocks_counter == 0)
std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str(); std::cout << "Can not read blocks from file " << filename.c_str() << "\nReason: " << errorMessage.str();

View File

@ -252,84 +252,15 @@ void validate_pointers(::std::atomic<int>& _progress, const char* _oldbase, ::pr
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
uint64_t write_block_recursive(float& _progress, float _prog_per_block, ::std::vector<char>& _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<uint16_t>(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<char>& _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<uint16_t>(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" { extern "C" {
PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename, PROFILER_API ::profiler::block_index_t fillTreesFromFile(::std::atomic<int>& progress, const char* filename,
::profiler::FileData& filedata, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& blocks, ::profiler::blocks_t& blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log) ::std::stringstream& _log)
{ {
@ -353,7 +284,8 @@ extern "C" {
stringstream_parent& s = str; stringstream_parent& s = str;
auto oldbuf = s.rdbuf(inFile.rdbuf()); 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); s.rdbuf(oldbuf);
return result; return result;
@ -362,10 +294,12 @@ extern "C" {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& inFile, PROFILER_API ::profiler::block_index_t fillTreesFromStream(::std::atomic<int>& progress, ::std::stringstream& inFile,
::profiler::FileData& filedata, ::profiler::SerializedData& serialized_blocks,
::profiler::SerializedData& serialized_descriptors,
::profiler::descriptors_list_t& descriptors, ::profiler::descriptors_list_t& descriptors,
::profiler::blocks_t& blocks, ::profiler::blocks_t& blocks,
::profiler::thread_blocks_tree_t& threaded_trees, ::profiler::thread_blocks_tree_t& threaded_trees,
uint32_t& total_descriptors_number,
bool gather_statistics, bool gather_statistics,
::std::stringstream& _log) ::std::stringstream& _log)
{ {
@ -394,24 +328,24 @@ extern "C" {
return 0; return 0;
} }
filedata.cpu_frequency = 0LL; int64_t cpu_frequency = 0LL;
inFile.read((char*)&filedata.cpu_frequency, sizeof(int64_t)); inFile.read((char*)&cpu_frequency, sizeof(int64_t));
filedata.begin_time = 0; ::profiler::timestamp_t begin_time = 0ULL;
filedata.end_time = 0; ::profiler::timestamp_t end_time = 0ULL;
inFile.read((char*)&filedata.begin_time, sizeof(::profiler::timestamp_t)); inFile.read((char*)&begin_time, sizeof(::profiler::timestamp_t));
inFile.read((char*)&filedata.end_time, sizeof(::profiler::timestamp_t)); inFile.read((char*)&end_time, sizeof(::profiler::timestamp_t));
if (filedata.cpu_frequency != 0) if (cpu_frequency != 0)
{ {
filedata.begin_time *= TIME_FACTOR; begin_time *= TIME_FACTOR;
filedata.begin_time /= filedata.cpu_frequency; begin_time /= cpu_frequency;
filedata.end_time *= TIME_FACTOR; end_time *= TIME_FACTOR;
filedata.end_time /= filedata.cpu_frequency; end_time /= cpu_frequency;
} }
filedata.total_blocks_number = 0; uint32_t total_blocks_number = 0;
inFile.read((char*)&filedata.total_blocks_number, sizeof(decltype(filedata.total_blocks_number))); inFile.read((char*)&total_blocks_number, sizeof(uint32_t));
if (filedata.total_blocks_number == 0) if (total_blocks_number == 0)
{ {
_log << "Profiled blocks number == 0"; _log << "Profiled blocks number == 0";
return 0; return 0;
@ -421,13 +355,13 @@ extern "C" {
inFile.read((char*)&memory_size, sizeof(decltype(memory_size))); inFile.read((char*)&memory_size, sizeof(decltype(memory_size)));
if (memory_size == 0) 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; return 0;
} }
filedata.total_descriptors_number = 0; total_descriptors_number = 0;
inFile.read((char*)&filedata.total_descriptors_number, sizeof(decltype(filedata.total_descriptors_number))); inFile.read((char*)&total_descriptors_number, sizeof(uint32_t));
if (filedata.total_descriptors_number == 0) if (total_descriptors_number == 0)
{ {
_log << "Blocks description number == 0"; _log << "Blocks description number == 0";
return 0; return 0;
@ -437,17 +371,17 @@ extern "C" {
inFile.read((char*)&descriptors_memory_size, sizeof(decltype(descriptors_memory_size))); inFile.read((char*)&descriptors_memory_size, sizeof(decltype(descriptors_memory_size)));
if (descriptors_memory_size == 0) 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; return 0;
} }
descriptors.reserve(filedata.total_descriptors_number); descriptors.reserve(total_descriptors_number);
//const char* olddata = append_regime ? filedata.serialized_descriptors.data() : nullptr; //const char* olddata = append_regime ? serialized_descriptors.data() : nullptr;
filedata.serialized_descriptors.set(descriptors_memory_size); serialized_descriptors.set(descriptors_memory_size);
//validate_pointers(progress, olddata, filedata.serialized_descriptors, descriptors, descriptors.size()); //validate_pointers(progress, olddata, serialized_descriptors, descriptors, descriptors.size());
uint64_t i = 0; 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; uint16_t sz = 0;
inFile.read((char*)&sz, sizeof(sz)); inFile.read((char*)&sz, sizeof(sz));
@ -462,7 +396,7 @@ extern "C" {
// return 0; // return 0;
//} //}
char* data = filedata.serialized_descriptors[i]; char* data = serialized_descriptors[i];
inFile.read(data, sz); inFile.read(data, sz);
auto descriptor = reinterpret_cast<::profiler::SerializedBlockDescriptor*>(data); auto descriptor = reinterpret_cast<::profiler::SerializedBlockDescriptor*>(data);
descriptors.push_back(descriptor); descriptors.push_back(descriptor);
@ -480,16 +414,16 @@ extern "C" {
PerThreadStats thread_statistics, parent_statistics, frame_statistics; PerThreadStats thread_statistics, parent_statistics, frame_statistics;
IdMap identification_table; IdMap identification_table;
blocks.reserve(filedata.total_blocks_number); blocks.reserve(total_blocks_number);
//olddata = append_regime ? filedata.serialized_blocks.data() : nullptr; //olddata = append_regime ? serialized_blocks.data() : nullptr;
filedata.serialized_blocks.set(memory_size); serialized_blocks.set(memory_size);
//validate_pointers(progress, olddata, filedata.serialized_blocks, blocks, blocks.size()); //validate_pointers(progress, olddata, serialized_blocks, blocks, blocks.size());
i = 0; i = 0;
uint32_t read_number = 0; uint32_t read_number = 0;
::profiler::block_index_t blocks_counter = 0; ::profiler::block_index_t blocks_counter = 0;
::std::vector<char> name; ::std::vector<char> 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); EASY_BLOCK("Read thread data", ::profiler::colors::DarkGreen);
@ -497,7 +431,6 @@ extern "C" {
inFile.read((char*)&thread_id, sizeof(decltype(thread_id))); inFile.read((char*)&thread_id, sizeof(decltype(thread_id)));
auto& root = threaded_trees[thread_id]; auto& root = threaded_trees[thread_id];
filedata.threads_order.push_back(thread_id);
uint16_t name_size = 0; uint16_t name_size = 0;
inFile.read((char*)&name_size, sizeof(uint16_t)); inFile.read((char*)&name_size, sizeof(uint16_t));
@ -525,25 +458,25 @@ extern "C" {
return 0; return 0;
} }
char* data = filedata.serialized_blocks[i]; char* data = serialized_blocks[i];
inFile.read(data, sz); inFile.read(data, sz);
i += sz; i += sz;
auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data);
auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data);
auto t_end = t_begin + 1; auto t_end = t_begin + 1;
if (filedata.cpu_frequency != 0) if (cpu_frequency != 0)
{ {
*t_begin *= TIME_FACTOR; *t_begin *= TIME_FACTOR;
*t_begin /= filedata.cpu_frequency; *t_begin /= cpu_frequency;
*t_end *= TIME_FACTOR; *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) if (*t_begin < begin_time)
*t_begin = filedata.begin_time; *t_begin = begin_time;
blocks.emplace_back(); blocks.emplace_back();
::profiler::BlocksTree& tree = blocks.back(); ::profiler::BlocksTree& tree = blocks.back();
@ -581,11 +514,11 @@ extern "C" {
return 0; return 0;
} }
char* data = filedata.serialized_blocks[i]; char* data = serialized_blocks[i];
inFile.read(data, sz); inFile.read(data, sz);
i += sz; i += sz;
auto baseData = reinterpret_cast<::profiler::SerializedBlock*>(data); 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(); _log << "Bad block id == " << baseData->id();
return 0; return 0;
@ -601,18 +534,18 @@ extern "C" {
auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data); auto t_begin = reinterpret_cast<::profiler::timestamp_t*>(data);
auto t_end = t_begin + 1; auto t_end = t_begin + 1;
if (filedata.cpu_frequency != 0) if (cpu_frequency != 0)
{ {
*t_begin *= TIME_FACTOR; *t_begin *= TIME_FACTOR;
*t_begin /= filedata.cpu_frequency; *t_begin /= cpu_frequency;
*t_end *= TIME_FACTOR; *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) if (*t_begin < begin_time)
*t_begin = filedata.begin_time; *t_begin = begin_time;
blocks.emplace_back(); blocks.emplace_back();
::profiler::BlocksTree& tree = blocks.back(); ::profiler::BlocksTree& tree = blocks.back();
@ -889,162 +822,4 @@ extern "C" {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
PROFILER_API bool writeTreesToFile(::std::atomic<int>& 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<int>& 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<const ::profiler::SerializedBlockDescriptor*>(data);
auto sz = static_cast<uint16_t>(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<int>(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<char> 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<uint16_t>(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<uint32_t>(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<int>(prog), ::std::memory_order_release);
if (oldprogress < 0)
{
_log << "Writing was interrupted";
return false; // Loading interrupted
}
}
blocks_number_in_thread = static_cast<uint32_t>(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<int>(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;
}
//////////////////////////////////////////////////////////////////////////
} }