mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-27 00:31:02 +08:00
Saving network data using temporary cache file + Question box when clicked on "Clear all"
This commit is contained in:
parent
817083d3ff
commit
dc01c49020
@ -78,7 +78,6 @@ namespace profiler {
|
||||
public:
|
||||
|
||||
typedef ::std::vector<This> blocks_t;
|
||||
typedef ::std::vector<This*> 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<int>& 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<int>& 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<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::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<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,
|
||||
@ -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<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
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include <QLabel>
|
||||
#include <QDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFile>
|
||||
|
||||
#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<EasyTreeWidget*>(m_treeWidget->widget())->clearSilent(true);
|
||||
static_cast<EasyGraphicsViewWidget*>(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<EasyTreeWidget*>(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<uint32_t>(descriptors.size());
|
||||
auto oldnumber = m_descriptorsNumberInFile;
|
||||
m_descriptorsNumberInFile = static_cast<uint32_t>(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;
|
||||
}
|
||||
|
@ -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<int> 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);
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
331
src/reader.cpp
331
src/reader.cpp
@ -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" {
|
||||
|
||||
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::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<int>& 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<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);
|
||||
|
||||
@ -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<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;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user