mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 16:11:02 +08:00
#0 [Core] refactoring
This commit is contained in:
parent
745609f1a4
commit
8c90ee7ef5
@ -112,16 +112,21 @@ message(STATUS "")
|
|||||||
#################################################
|
#################################################
|
||||||
# Add source files:
|
# Add source files:
|
||||||
set(CPP_FILES
|
set(CPP_FILES
|
||||||
|
base_block_descriptor.cpp
|
||||||
block.cpp
|
block.cpp
|
||||||
|
block_descriptor.cpp
|
||||||
easy_socket.cpp
|
easy_socket.cpp
|
||||||
event_trace_win.cpp
|
event_trace_win.cpp
|
||||||
nonscoped_block.cpp
|
nonscoped_block.cpp
|
||||||
profile_manager.cpp
|
profile_manager.cpp
|
||||||
|
profiler.cpp
|
||||||
reader.cpp
|
reader.cpp
|
||||||
|
serialized_block.cpp
|
||||||
thread_storage.cpp
|
thread_storage.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(H_FILES
|
set(H_FILES
|
||||||
|
block_descriptor.h
|
||||||
chunk_allocator.h
|
chunk_allocator.h
|
||||||
current_time.h
|
current_time.h
|
||||||
current_thread.h
|
current_thread.h
|
||||||
|
59
easy_profiler_core/base_block_descriptor.cpp
Normal file
59
easy_profiler_core/base_block_descriptor.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
Lightweight profiler library for c++
|
||||||
|
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
|
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
The Apache License, Version 2.0 (the "License");
|
||||||
|
You may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <easy/details/profiler_public_types.h>
|
||||||
|
|
||||||
|
namespace profiler
|
||||||
|
{
|
||||||
|
|
||||||
|
BaseBlockDescriptor::BaseBlockDescriptor(block_id_t _id, EasyBlockStatus _status, int _line,
|
||||||
|
block_type_t _block_type, color_t _color) EASY_NOEXCEPT
|
||||||
|
: m_id(_id)
|
||||||
|
, m_line(_line)
|
||||||
|
, m_type(_block_type)
|
||||||
|
, m_color(_color)
|
||||||
|
, m_status(_status)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace profiler.
|
92
easy_profiler_core/block_descriptor.cpp
Normal file
92
easy_profiler_core/block_descriptor.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
Lightweight profiler library for c++
|
||||||
|
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
|
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
The Apache License, Version 2.0 (the "License");
|
||||||
|
You may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include "block_descriptor.h"
|
||||||
|
|
||||||
|
#if EASY_BLOCK_DESC_FULL_COPY == 0
|
||||||
|
# define EASY_BLOCK_DESC_STRING_LEN(s) static_cast<uint16_t>(strlen(s) + 1)
|
||||||
|
# define EASY_BLOCK_DESC_STRING_VAL(s) s
|
||||||
|
#else
|
||||||
|
# define EASY_BLOCK_DESC_STRING_LEN(s) static_cast<uint16_t>(s.size() + 1)
|
||||||
|
# define EASY_BLOCK_DESC_STRING_VAL(s) s.c_str()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BlockDescriptor::BlockDescriptor(profiler::block_id_t _id, profiler::EasyBlockStatus _status, const char* _name,
|
||||||
|
const char* _filename, int _line, profiler::block_type_t _block_type,
|
||||||
|
profiler::color_t _color)
|
||||||
|
: Parent(_id, _status, _line, _block_type, _color)
|
||||||
|
, m_filename(_filename)
|
||||||
|
, m_name(_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* BlockDescriptor::name() const
|
||||||
|
{
|
||||||
|
return EASY_BLOCK_DESC_STRING_VAL(m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* BlockDescriptor::filename() const
|
||||||
|
{
|
||||||
|
return EASY_BLOCK_DESC_STRING_VAL(m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BlockDescriptor::nameSize() const
|
||||||
|
{
|
||||||
|
return EASY_BLOCK_DESC_STRING_LEN(m_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BlockDescriptor::filenameSize() const
|
||||||
|
{
|
||||||
|
return EASY_BLOCK_DESC_STRING_LEN(m_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDescriptor::destroy(BlockDescriptor* instance)
|
||||||
|
{
|
||||||
|
#if EASY_BLOCK_DESC_FULL_COPY == 0
|
||||||
|
if (instance != nullptr)
|
||||||
|
instance->~BlockDescriptor();
|
||||||
|
free(instance);
|
||||||
|
#else
|
||||||
|
delete instance;
|
||||||
|
#endif
|
||||||
|
}
|
86
easy_profiler_core/block_descriptor.h
Normal file
86
easy_profiler_core/block_descriptor.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
Lightweight profiler library for c++
|
||||||
|
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
|
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
The Apache License, Version 2.0 (the "License");
|
||||||
|
You may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef EASY_PROFILER_BLOCK_DESCRIPTOR_H
|
||||||
|
#define EASY_PROFILER_BLOCK_DESCRIPTOR_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <easy/details/profiler_public_types.h>
|
||||||
|
|
||||||
|
#ifndef EASY_BLOCK_DESC_FULL_COPY
|
||||||
|
# define EASY_BLOCK_DESC_FULL_COPY 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class BlockDescriptor : public profiler::BaseBlockDescriptor
|
||||||
|
{
|
||||||
|
friend ProfileManager;
|
||||||
|
|
||||||
|
using Parent = profiler::BaseBlockDescriptor;
|
||||||
|
|
||||||
|
#if EASY_BLOCK_DESC_FULL_COPY == 0
|
||||||
|
using string_t = const char*;
|
||||||
|
#else
|
||||||
|
using string_t = std::string;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
string_t m_filename; ///< Source file name where this block is declared
|
||||||
|
string_t m_name; ///< Static name of all blocks of the same type (blocks can have dynamic name) which is, in pair with descriptor id, a unique block identifier
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BlockDescriptor() = delete;
|
||||||
|
BlockDescriptor(const BlockDescriptor&) = delete;
|
||||||
|
BlockDescriptor& operator = (const BlockDescriptor&) = delete;
|
||||||
|
|
||||||
|
BlockDescriptor(profiler::block_id_t _id, profiler::EasyBlockStatus _status, const char* _name,
|
||||||
|
const char* _filename, int _line, profiler::block_type_t _block_type, profiler::color_t _color);
|
||||||
|
|
||||||
|
const char* name() const;
|
||||||
|
const char* filename() const;
|
||||||
|
uint16_t nameSize() const;
|
||||||
|
uint16_t filenameSize() const;
|
||||||
|
|
||||||
|
static void destroy(BlockDescriptor* instance);
|
||||||
|
|
||||||
|
}; // END of class BlockDescriptor.
|
||||||
|
|
||||||
|
#endif //EASY_PROFILER_BLOCK_DESCRIPTOR_H
|
@ -45,7 +45,7 @@ The Apache License, Version 2.0 (the "License");
|
|||||||
|
|
||||||
#include <easy/details/easy_compiler_support.h>
|
#include <easy/details/easy_compiler_support.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "outstream.h"
|
#include <ostream>
|
||||||
#include "alignment_helpers.h"
|
#include "alignment_helpers.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@ -261,7 +261,7 @@ public:
|
|||||||
|
|
||||||
\warning Data will be cleared after serialization.
|
\warning Data will be cleared after serialization.
|
||||||
*/
|
*/
|
||||||
void serialize(profiler::OStream& _outputStream)
|
void serialize(std::ostream& _outputStream)
|
||||||
{
|
{
|
||||||
// Chunks are stored in reversed order (stack).
|
// Chunks are stored in reversed order (stack).
|
||||||
// To be able to iterate them in direct order we have to invert the chunks list.
|
// To be able to iterate them in direct order we have to invert the chunks list.
|
||||||
|
@ -63,146 +63,6 @@
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#if 0 == 1//defined(_MSC_VER)// && _MSC_VER >= 1800
|
|
||||||
# define EASY_PROFILER_HASHED_CSTR_DEFINED
|
|
||||||
|
|
||||||
namespace profiler {
|
|
||||||
|
|
||||||
/** \brief Simple C-string pointer with length.
|
|
||||||
|
|
||||||
It is used as base class for a key in std::unordered_map.
|
|
||||||
It is used to get better performance than std::string.
|
|
||||||
It simply stores a pointer and a length, there is no
|
|
||||||
any memory allocation and copy.
|
|
||||||
|
|
||||||
\warning Make sure you know what you are doing. You have to be sure that
|
|
||||||
pointed C-string will exist until you finish using this cstring.
|
|
||||||
|
|
||||||
\ingroup profiler
|
|
||||||
*/
|
|
||||||
class cstring
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
const char* m_str;
|
|
||||||
size_t m_len;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
cstring(const char* _str) : m_str(_str), m_len(strlen(_str))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
cstring(const char* _str, size_t _len) : m_str(_str), m_len(_len)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
cstring(const cstring&) = default;
|
|
||||||
cstring& operator = (const cstring&) = default;
|
|
||||||
|
|
||||||
inline bool operator == (const cstring& _other) const
|
|
||||||
{
|
|
||||||
return m_len == _other.m_len && !strncmp(m_str, _other.m_str, m_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const cstring& _other) const
|
|
||||||
{
|
|
||||||
return !operator == (_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator < (const cstring& _other) const
|
|
||||||
{
|
|
||||||
if (m_len == _other.m_len)
|
|
||||||
{
|
|
||||||
return strncmp(m_str, _other.m_str, m_len) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_len < _other.m_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const char* c_str() const
|
|
||||||
{
|
|
||||||
return m_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t size() const
|
|
||||||
{
|
|
||||||
return m_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // END of class cstring.
|
|
||||||
|
|
||||||
/** \brief cstring with precalculated hash.
|
|
||||||
|
|
||||||
This is used to calculate hash for C-string and to cache it
|
|
||||||
to be used in the future without recurring hash calculatoin.
|
|
||||||
|
|
||||||
\note This class is used as a key in std::unordered_map.
|
|
||||||
|
|
||||||
\ingroup profiler
|
|
||||||
*/
|
|
||||||
class hashed_cstr : public cstring
|
|
||||||
{
|
|
||||||
typedef cstring Parent;
|
|
||||||
|
|
||||||
size_t m_hash;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
hashed_cstr(const char* _str) : Parent(_str), m_hash(0)
|
|
||||||
{
|
|
||||||
m_hash = ::std::_Hash_seq((const unsigned char *)m_str, m_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
hashed_cstr(const char* _str, size_t _hash_code) : Parent(_str), m_hash(_hash_code)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
hashed_cstr(const char* _str, size_t _len, size_t _hash_code) : Parent(_str, _len), m_hash(_hash_code)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
hashed_cstr(const hashed_cstr&) = default;
|
|
||||||
hashed_cstr& operator = (const hashed_cstr&) = default;
|
|
||||||
|
|
||||||
inline bool operator == (const hashed_cstr& _other) const
|
|
||||||
{
|
|
||||||
return m_hash == _other.m_hash && Parent::operator == (_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator != (const hashed_cstr& _other) const
|
|
||||||
{
|
|
||||||
return !operator == (_other);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline size_t hcode() const
|
|
||||||
{
|
|
||||||
return m_hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // END of class hashed_cstr.
|
|
||||||
|
|
||||||
} // END of namespace profiler.
|
|
||||||
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
/** \brief Simply returns precalculated hash of a C-string. */
|
|
||||||
template <> struct hash<::profiler::hashed_cstr> {
|
|
||||||
typedef ::profiler::hashed_cstr argument_type;
|
|
||||||
typedef size_t result_type;
|
|
||||||
inline size_t operator () (const ::profiler::hashed_cstr& _str) const {
|
|
||||||
return _str.hcode();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // END of namespace std.
|
|
||||||
|
|
||||||
#else ////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// TODO: Create hashed_cstr for Linux (need to use Linux version of std::_Hash_seq)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace profiler {
|
namespace profiler {
|
||||||
|
|
||||||
class hashed_stdstring
|
class hashed_stdstring
|
||||||
@ -292,6 +152,155 @@ namespace std {
|
|||||||
|
|
||||||
} // END of namespace std.
|
} // END of namespace std.
|
||||||
|
|
||||||
|
#if 0 == 1 //defined(_MSC_VER)// && _MSC_VER >= 1800
|
||||||
|
# define EASY_PROFILER_HASHED_CSTR_DEFINED
|
||||||
|
|
||||||
|
namespace profiler {
|
||||||
|
|
||||||
|
/** \brief Simple C-string pointer with length.
|
||||||
|
|
||||||
|
It is used as base class for a key in std::unordered_map.
|
||||||
|
It is used to get better performance than std::string.
|
||||||
|
It simply stores a pointer and a length, there is no
|
||||||
|
any memory allocation and copy.
|
||||||
|
|
||||||
|
\warning Make sure you know what you are doing. You have to be sure that
|
||||||
|
pointed C-string will exist until you finish using this cstring.
|
||||||
|
|
||||||
|
\ingroup profiler
|
||||||
|
*/
|
||||||
|
class cstring
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char* m_str;
|
||||||
|
size_t m_len;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
cstring(const char* _str) : m_str(_str), m_len(strlen(_str))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cstring(const char* _str, size_t _len) : m_str(_str), m_len(_len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cstring(const cstring&) = default;
|
||||||
|
cstring& operator = (const cstring&) = default;
|
||||||
|
|
||||||
|
inline bool operator == (const cstring& _other) const
|
||||||
|
{
|
||||||
|
return m_len == _other.m_len && !strncmp(m_str, _other.m_str, m_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator != (const cstring& _other) const
|
||||||
|
{
|
||||||
|
return !operator == (_other);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator < (const cstring& _other) const
|
||||||
|
{
|
||||||
|
if (m_len == _other.m_len)
|
||||||
|
{
|
||||||
|
return strncmp(m_str, _other.m_str, m_len) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_len < _other.m_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char* c_str() const
|
||||||
|
{
|
||||||
|
return m_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t size() const
|
||||||
|
{
|
||||||
|
return m_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // END of class cstring.
|
||||||
|
|
||||||
|
/** \brief cstring with precalculated hash.
|
||||||
|
|
||||||
|
This is used to calculate hash for C-string and to cache it
|
||||||
|
to be used in the future without recurring hash calculatoin.
|
||||||
|
|
||||||
|
\note This class is used as a key in std::unordered_map.
|
||||||
|
|
||||||
|
\ingroup profiler
|
||||||
|
*/
|
||||||
|
class hashed_cstr : public cstring
|
||||||
|
{
|
||||||
|
using Parent = cstring;
|
||||||
|
|
||||||
|
size_t m_hash;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
hashed_cstr(const char* _str) : Parent(_str), m_hash(0)
|
||||||
|
{
|
||||||
|
m_hash = ::std::_Hash_seq((const unsigned char *)m_str, m_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_cstr(const char* _str, size_t _hash_code) : Parent(_str), m_hash(_hash_code)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_cstr(const char* _str, size_t _len, size_t _hash_code) : Parent(_str, _len), m_hash(_hash_code)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
hashed_cstr(const hashed_cstr&) = default;
|
||||||
|
hashed_cstr& operator = (const hashed_cstr&) = default;
|
||||||
|
|
||||||
|
inline bool operator == (const hashed_cstr& _other) const
|
||||||
|
{
|
||||||
|
return m_hash == _other.m_hash && Parent::operator == (_other);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator != (const hashed_cstr& _other) const
|
||||||
|
{
|
||||||
|
return !operator == (_other);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t hcode() const
|
||||||
|
{
|
||||||
|
return m_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // END of class hashed_cstr.
|
||||||
|
|
||||||
|
using string_with_hash = hashed_cstr;
|
||||||
|
|
||||||
|
} // END of namespace profiler.
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
/** \brief Simply returns precalculated hash of a C-string. */
|
||||||
|
template <> struct hash<::profiler::hashed_cstr>
|
||||||
|
{
|
||||||
|
using argument_type = ::profiler::hashed_cstr;
|
||||||
|
using result_type = size_t;
|
||||||
|
|
||||||
|
inline size_t operator () (const ::profiler::hashed_cstr& _str) const
|
||||||
|
{
|
||||||
|
return _str.hcode();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // END of namespace std.
|
||||||
|
|
||||||
|
#else ////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// TODO: Create hashed_cstr for Linux (need to use Linux version of std::_Hash_seq)
|
||||||
|
|
||||||
|
namespace profiler {
|
||||||
|
using string_with_hash = hashed_stdstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -1,115 +0,0 @@
|
|||||||
/************************************************************************
|
|
||||||
* file name : outstream.h
|
|
||||||
* ----------------- :
|
|
||||||
* creation time : 2016/09/11
|
|
||||||
* authors : Sergey Yagovtsev, Victor Zarubkin
|
|
||||||
* emails : yse.sey@gmail.com, v.s.zarubkin@gmail.com
|
|
||||||
* ----------------- :
|
|
||||||
* description : The file contains definition of output stream helpers.
|
|
||||||
* ----------------- :
|
|
||||||
* change log : * 2016/09/11 Victor Zarubkin: Initial commit. Moved sources from profiler_manager.h/.cpp
|
|
||||||
* :
|
|
||||||
* : *
|
|
||||||
* ----------------- :
|
|
||||||
* license : Lightweight profiler library for c++
|
|
||||||
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
|
||||||
* :
|
|
||||||
* : Licensed under either of
|
|
||||||
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
|
||||||
* : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
* : at your option.
|
|
||||||
* :
|
|
||||||
* : The MIT License
|
|
||||||
* :
|
|
||||||
* : Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* : of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* : in the Software without restriction, including without limitation the rights
|
|
||||||
* : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
* : of the Software, and to permit persons to whom the Software is furnished
|
|
||||||
* : to do so, subject to the following conditions:
|
|
||||||
* :
|
|
||||||
* : The above copyright notice and this permission notice shall be included in all
|
|
||||||
* : copies or substantial portions of the Software.
|
|
||||||
* :
|
|
||||||
* : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
||||||
* : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
* : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
* : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
* : USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
* :
|
|
||||||
* : The Apache License, Version 2.0 (the "License")
|
|
||||||
* :
|
|
||||||
* : You may not use this file except in compliance with the License.
|
|
||||||
* : You may obtain a copy of the License at
|
|
||||||
* :
|
|
||||||
* : http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* :
|
|
||||||
* : Unless required by applicable law or agreed to in writing, software
|
|
||||||
* : distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* : See the License for the specific language governing permissions and
|
|
||||||
* : limitations under the License.
|
|
||||||
************************************************************************/
|
|
||||||
|
|
||||||
#ifndef EASY_PROFILER__OUTPUT_STREAM__H_
|
|
||||||
#define EASY_PROFILER__OUTPUT_STREAM__H_
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
namespace profiler {
|
|
||||||
|
|
||||||
class OStream
|
|
||||||
{
|
|
||||||
::std::stringstream m_stream;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit OStream() : m_stream(std::ios_base::out | std::ios_base::binary)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> void write(const char* _data, T _size)
|
|
||||||
{
|
|
||||||
m_stream.write(_data, _size);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void write(const T& _data)
|
|
||||||
{
|
|
||||||
m_stream.write((const char*)&_data, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
::std::stringstream& stream()
|
|
||||||
{
|
|
||||||
return m_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ::std::stringstream& stream() const
|
|
||||||
{
|
|
||||||
return m_stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
#if defined(__GNUC__) && __GNUC__ < 5
|
|
||||||
// gcc 4 has a known bug which has been solved in gcc 5:
|
|
||||||
// std::stringstream has no swap() method :(
|
|
||||||
m_stream.str(::std::string());
|
|
||||||
#else
|
|
||||||
::std::stringstream().swap(m_stream);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // END of class OStream.
|
|
||||||
|
|
||||||
} // END of namespace profiler.
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#endif // EASY_PROFILER__OUTPUT_STREAM__H_
|
|
File diff suppressed because it is too large
Load Diff
@ -52,16 +52,17 @@ The Apache License, Version 2.0 (the "License");
|
|||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
#include "spin_lock.h"
|
#include "spin_lock.h"
|
||||||
#include "outstream.h"
|
|
||||||
#include "hashed_cstr.h"
|
#include "hashed_cstr.h"
|
||||||
#include "thread_storage.h"
|
#include "thread_storage.h"
|
||||||
|
#include "current_time.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <ostream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -69,7 +70,9 @@ using processid_t = uint64_t;
|
|||||||
|
|
||||||
class BlockDescriptor;
|
class BlockDescriptor;
|
||||||
|
|
||||||
namespace profiler { class ValueId; }
|
namespace profiler {
|
||||||
|
class ValueId;
|
||||||
|
}
|
||||||
|
|
||||||
class ProfileManager
|
class ProfileManager
|
||||||
{
|
{
|
||||||
@ -79,23 +82,27 @@ class ProfileManager
|
|||||||
|
|
||||||
ProfileManager();
|
ProfileManager();
|
||||||
|
|
||||||
using atomic_timestamp_t = std::atomic<profiler::timestamp_t>;
|
using atomic_timestamp_t = std::atomic<profiler::timestamp_t>;
|
||||||
using guard_lock_t = profiler::guard_lock<profiler::spin_lock>;
|
using guard_lock_t = profiler::guard_lock<profiler::spin_lock>;
|
||||||
using map_of_threads_stacks = std::map<profiler::thread_id_t, ThreadStorage>;
|
using map_of_threads_stacks = std::map<profiler::thread_id_t, ThreadStorage>;
|
||||||
using block_descriptors_t = std::vector<BlockDescriptor*>;
|
using block_descriptors_t = std::vector<BlockDescriptor*>;
|
||||||
|
using descriptors_map_t = std::unordered_map<profiler::string_with_hash, profiler::block_id_t>;
|
||||||
#ifdef EASY_PROFILER_HASHED_CSTR_DEFINED
|
|
||||||
using descriptors_map_t = std::unordered_map<profiler::hashed_cstr, profiler::block_id_t>;
|
|
||||||
#else
|
|
||||||
using descriptors_map_t = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const processid_t m_processId;
|
const processid_t m_processId;
|
||||||
|
|
||||||
|
#if defined(EASY_CHRONO_CLOCK) || defined(_WIN32)
|
||||||
|
const int64_t m_cpuFrequency;
|
||||||
|
#endif
|
||||||
|
|
||||||
map_of_threads_stacks m_threads;
|
map_of_threads_stacks m_threads;
|
||||||
block_descriptors_t m_descriptors;
|
block_descriptors_t m_descriptors;
|
||||||
descriptors_map_t m_descriptorsMap;
|
descriptors_map_t m_descriptorsMap;
|
||||||
uint64_t m_descriptorsMemorySize;
|
uint64_t m_descriptorsMemorySize;
|
||||||
|
|
||||||
|
#if !defined(EASY_CHRONO_CLOCK) && !defined(_WIN32)
|
||||||
|
std::atomic<int64_t> m_cpuFrequency;
|
||||||
|
#endif
|
||||||
|
|
||||||
profiler::timestamp_t m_beginTime;
|
profiler::timestamp_t m_beginTime;
|
||||||
profiler::timestamp_t m_endTime;
|
profiler::timestamp_t m_endTime;
|
||||||
atomic_timestamp_t m_frameMax;
|
atomic_timestamp_t m_frameMax;
|
||||||
@ -114,13 +121,8 @@ class ProfileManager
|
|||||||
|
|
||||||
std::string m_csInfoFilename = "/tmp/cs_profiling_info.log";
|
std::string m_csInfoFilename = "/tmp/cs_profiling_info.log";
|
||||||
|
|
||||||
uint32_t dumpBlocksToStream(profiler::OStream& _outputStream, bool _lockSpin, bool _async);
|
std::thread m_listenThread;
|
||||||
void setBlockStatus(profiler::block_id_t _id, profiler::EasyBlockStatus _status);
|
std::atomic_bool m_stopListen;
|
||||||
|
|
||||||
std::thread m_listenThread;
|
|
||||||
void listen(uint16_t _port);
|
|
||||||
|
|
||||||
std::atomic_bool m_stopListen;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -147,6 +149,7 @@ public:
|
|||||||
void beginBlock(profiler::Block& _block);
|
void beginBlock(profiler::Block& _block);
|
||||||
void beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
|
void beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
|
||||||
void endBlock();
|
void endBlock();
|
||||||
|
|
||||||
profiler::timestamp_t maxFrameDuration();
|
profiler::timestamp_t maxFrameDuration();
|
||||||
profiler::timestamp_t avgFrameDuration();
|
profiler::timestamp_t avgFrameDuration();
|
||||||
profiler::timestamp_t curFrameDuration() const;
|
profiler::timestamp_t curFrameDuration() const;
|
||||||
@ -162,15 +165,8 @@ public:
|
|||||||
const char* registerThread(const char* name, profiler::ThreadGuard& threadGuard);
|
const char* registerThread(const char* name, profiler::ThreadGuard& threadGuard);
|
||||||
const char* registerThread(const char* name);
|
const char* registerThread(const char* name);
|
||||||
|
|
||||||
void setContextSwitchLogFilename(const char* name)
|
void setContextSwitchLogFilename(const char* name);
|
||||||
{
|
const char* getContextSwitchLogFilename() const;
|
||||||
m_csInfoFilename = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* getContextSwitchLogFilename() const
|
|
||||||
{
|
|
||||||
return m_csInfoFilename.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void beginContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, const char* _target_process, bool _lockSpin = true);
|
void beginContextSwitch(profiler::thread_id_t _thread_id, profiler::timestamp_t _time, profiler::thread_id_t _target_thread_id, const char* _target_process, bool _lockSpin = true);
|
||||||
void endContextSwitch(profiler::thread_id_t _thread_id, processid_t _process_id, profiler::timestamp_t _endtime, bool _lockSpin = true);
|
void endContextSwitch(profiler::thread_id_t _thread_id, processid_t _process_id, profiler::timestamp_t _endtime, bool _lockSpin = true);
|
||||||
@ -178,8 +174,24 @@ public:
|
|||||||
void stopListen();
|
void stopListen();
|
||||||
bool isListening() const;
|
bool isListening() const;
|
||||||
|
|
||||||
|
profiler::timestamp_t ticks2ns(profiler::timestamp_t ticks) const;
|
||||||
|
profiler::timestamp_t ticks2us(profiler::timestamp_t ticks) const;
|
||||||
|
|
||||||
|
static bool isMainThread();
|
||||||
|
static profiler::timestamp_t this_thread_frameTime(profiler::Duration _durationCast);
|
||||||
|
static profiler::timestamp_t this_thread_frameTimeLocalMax(profiler::Duration _durationCast);
|
||||||
|
static profiler::timestamp_t this_thread_frameTimeLocalAvg(profiler::Duration _durationCast);
|
||||||
|
static profiler::timestamp_t main_thread_frameTime(profiler::Duration _durationCast);
|
||||||
|
static profiler::timestamp_t main_thread_frameTimeLocalMax(profiler::Duration _durationCast);
|
||||||
|
static profiler::timestamp_t main_thread_frameTimeLocalAvg(profiler::Duration _durationCast);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void listen(uint16_t _port);
|
||||||
|
|
||||||
|
uint32_t dumpBlocksToStream(std::ostream& _outputStream, bool _lockSpin, bool _async);
|
||||||
|
void setBlockStatus(profiler::block_id_t _id, profiler::EasyBlockStatus _status);
|
||||||
|
|
||||||
void registerThread();
|
void registerThread();
|
||||||
|
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
@ -196,13 +208,13 @@ private:
|
|||||||
ThreadStorage& _threadStorage(profiler::thread_id_t _thread_id);
|
ThreadStorage& _threadStorage(profiler::thread_id_t _thread_id);
|
||||||
ThreadStorage* _findThreadStorage(profiler::thread_id_t _thread_id);
|
ThreadStorage* _findThreadStorage(profiler::thread_id_t _thread_id);
|
||||||
|
|
||||||
inline ThreadStorage& threadStorage(profiler::thread_id_t _thread_id)
|
ThreadStorage& threadStorage(profiler::thread_id_t _thread_id)
|
||||||
{
|
{
|
||||||
guard_lock_t lock(m_spin);
|
guard_lock_t lock(m_spin);
|
||||||
return _threadStorage(_thread_id);
|
return _threadStorage(_thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ThreadStorage* findThreadStorage(profiler::thread_id_t _thread_id)
|
ThreadStorage* findThreadStorage(profiler::thread_id_t _thread_id)
|
||||||
{
|
{
|
||||||
guard_lock_t lock(m_spin);
|
guard_lock_t lock(m_spin);
|
||||||
return _findThreadStorage(_thread_id);
|
return _findThreadStorage(_thread_id);
|
||||||
|
348
easy_profiler_core/profiler.cpp
Normal file
348
easy_profiler_core/profiler.cpp
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* file name : profiler.cpp
|
||||||
|
* ----------------- :
|
||||||
|
* creation time : 2018/05/06
|
||||||
|
* authors : Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
* emails : yse.sey@gmail.com, v.s.zarubkin@gmail.com
|
||||||
|
* ----------------- :
|
||||||
|
* description : The file contains implementation of Profile manager and implement access c-function
|
||||||
|
* :
|
||||||
|
* license : Lightweight profiler library for c++
|
||||||
|
* : Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
* :
|
||||||
|
* : Licensed under either of
|
||||||
|
* : * MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
|
* : * Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
* : at your option.
|
||||||
|
* :
|
||||||
|
* : The MIT License
|
||||||
|
* :
|
||||||
|
* : Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* : of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* : in the Software without restriction, including without limitation the rights
|
||||||
|
* : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
* : of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
* : to do so, subject to the following conditions:
|
||||||
|
* :
|
||||||
|
* : The above copyright notice and this permission notice shall be included in all
|
||||||
|
* : copies or substantial portions of the Software.
|
||||||
|
* :
|
||||||
|
* : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* : INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* : PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* : TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
* : USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
* :
|
||||||
|
* : The Apache License, Version 2.0 (the "License")
|
||||||
|
* :
|
||||||
|
* : You may not use this file except in compliance with the License.
|
||||||
|
* : You may obtain a copy of the License at
|
||||||
|
* :
|
||||||
|
* : http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* :
|
||||||
|
* : Unless required by applicable law or agreed to in writing, software
|
||||||
|
* : distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* : See the License for the specific language governing permissions and
|
||||||
|
* : limitations under the License.
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
#include <easy/profiler.h>
|
||||||
|
#include <easy/arbitrary_value.h>
|
||||||
|
#include "current_time.h"
|
||||||
|
#include "profile_manager.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef BUILD_WITH_EASY_PROFILER
|
||||||
|
# ifndef EASY_PROFILER_API_DISABLED
|
||||||
|
# define EASY_PROFILER_API_DISABLED
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(EASY_PROFILER_VERSION_MAJOR) || !defined(EASY_PROFILER_VERSION_MINOR) || !defined(EASY_PROFILER_VERSION_PATCH)
|
||||||
|
# ifdef _WIN32
|
||||||
|
# error EASY_PROFILER_VERSION_MAJOR and EASY_PROFILER_VERSION_MINOR and EASY_PROFILER_VERSION_PATCH macros must be defined
|
||||||
|
# else
|
||||||
|
# error "EASY_PROFILER_VERSION_MAJOR and EASY_PROFILER_VERSION_MINOR and EASY_PROFILER_VERSION_PATCH macros must be defined"
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define EASY_PROFILER_PRODUCT_VERSION "v" EASY_STRINGIFICATION(EASY_PROFILER_VERSION_MAJOR) "." \
|
||||||
|
EASY_STRINGIFICATION(EASY_PROFILER_VERSION_MINOR) "." \
|
||||||
|
EASY_STRINGIFICATION(EASY_PROFILER_VERSION_PATCH)
|
||||||
|
|
||||||
|
extern const uint32_t EASY_PROFILER_SIGNATURE = ('E' << 24) | ('a' << 16) | ('s' << 8) | 'y';
|
||||||
|
extern const uint32_t EASY_PROFILER_VERSION = (static_cast<uint32_t>(EASY_PROFILER_VERSION_MAJOR) << 24) |
|
||||||
|
(static_cast<uint32_t>(EASY_PROFILER_VERSION_MINOR) << 16) |
|
||||||
|
static_cast<uint32_t>(EASY_PROFILER_VERSION_PATCH);
|
||||||
|
|
||||||
|
#undef EASY_VERSION_INT
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
PROFILER_API uint8_t versionMajor()
|
||||||
|
{
|
||||||
|
static_assert(0 <= EASY_PROFILER_VERSION_MAJOR && EASY_PROFILER_VERSION_MAJOR <= 255,
|
||||||
|
"EASY_PROFILER_VERSION_MAJOR must be defined in range [0, 255]");
|
||||||
|
|
||||||
|
return EASY_PROFILER_VERSION_MAJOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API uint8_t versionMinor()
|
||||||
|
{
|
||||||
|
static_assert(0 <= EASY_PROFILER_VERSION_MINOR && EASY_PROFILER_VERSION_MINOR <= 255,
|
||||||
|
"EASY_PROFILER_VERSION_MINOR must be defined in range [0, 255]");
|
||||||
|
|
||||||
|
return EASY_PROFILER_VERSION_MINOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API uint16_t versionPatch()
|
||||||
|
{
|
||||||
|
static_assert(0 <= EASY_PROFILER_VERSION_PATCH && EASY_PROFILER_VERSION_PATCH <= 65535,
|
||||||
|
"EASY_PROFILER_VERSION_PATCH must be defined in range [0, 65535]");
|
||||||
|
|
||||||
|
return EASY_PROFILER_VERSION_PATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API uint32_t version()
|
||||||
|
{
|
||||||
|
return EASY_PROFILER_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API const char* versionName()
|
||||||
|
{
|
||||||
|
#ifdef EASY_PROFILER_API_DISABLED
|
||||||
|
return EASY_PROFILER_PRODUCT_VERSION "_disabled";
|
||||||
|
#else
|
||||||
|
return EASY_PROFILER_PRODUCT_VERSION;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if !defined(EASY_PROFILER_API_DISABLED)
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t now()
|
||||||
|
{
|
||||||
|
return profiler::clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t toNanoseconds(profiler::timestamp_t _ticks)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().ticks2ns(_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t toMicroseconds(profiler::timestamp_t _ticks)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().ticks2us(_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API const profiler::BaseBlockDescriptor*
|
||||||
|
registerDescription(profiler::EasyBlockStatus _status, const char* _autogenUniqueId, const char* _name,
|
||||||
|
const char* _filename, int _line, profiler::block_type_t _block_type, profiler::color_t _color,
|
||||||
|
bool _copyName)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().addBlockDescriptor(_status, _autogenUniqueId, _name, _filename, _line,
|
||||||
|
_block_type, _color, _copyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void endBlock()
|
||||||
|
{
|
||||||
|
ProfileManager::instance().endBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void setEnabled(bool isEnable)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().setEnabled(isEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API bool isEnabled()
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void storeValue(const profiler::BaseBlockDescriptor* _desc, profiler::DataType _type, const void* _data,
|
||||||
|
uint16_t _size, bool _isArray, profiler::ValueId _vin)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().storeValue(_desc, _type, _data, _size, _isArray, _vin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void storeEvent(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().storeBlock(_desc, _runtimeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void storeBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName,
|
||||||
|
profiler::timestamp_t _beginTime, profiler::timestamp_t _endTime)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().storeBlock(_desc, _runtimeName, _beginTime, _endTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void beginBlock(profiler::Block& _block)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().beginBlock(_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().beginNonScopedBlock(_desc, _runtimeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API uint32_t dumpBlocksToFile(const char* filename)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().dumpBlocksToFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API const char* registerThreadScoped(const char* name, profiler::ThreadGuard& threadGuard)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().registerThread(name, threadGuard);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API const char* registerThread(const char* name)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().registerThread(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void setEventTracingEnabled(bool _isEnable)
|
||||||
|
{
|
||||||
|
ProfileManager::instance().setEventTracingEnabled(_isEnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API bool isEventTracingEnabled()
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().isEventTracingEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef _WIN32
|
||||||
|
PROFILER_API void setLowPriorityEventTracing(bool _isLowPriority)
|
||||||
|
{
|
||||||
|
EasyEventTracer::instance().setLowPriority(_isLowPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API bool isLowPriorityEventTracing()
|
||||||
|
{
|
||||||
|
return EasyEventTracer::instance().isLowPriority();
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
PROFILER_API void setLowPriorityEventTracing(bool) { }
|
||||||
|
PROFILER_API bool isLowPriorityEventTracing() { return false; }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
PROFILER_API void setContextSwitchLogFilename(const char* name)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().setContextSwitchLogFilename(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API const char* getContextSwitchLogFilename()
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().getContextSwitchLogFilename();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void startListen(uint16_t _port)
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().startListen(_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void stopListen()
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().stopListen();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API bool isListening()
|
||||||
|
{
|
||||||
|
return ProfileManager::instance().isListening();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API bool isMainThread()
|
||||||
|
{
|
||||||
|
return ProfileManager::isMainThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTime(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::this_thread_frameTime(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTimeLocalMax(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::this_thread_frameTimeLocalMax(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTimeLocalAvg(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::this_thread_frameTimeLocalAvg(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTime(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::main_thread_frameTime(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTimeLocalMax(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::main_thread_frameTimeLocalMax(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTimeLocalAvg(profiler::Duration _durationCast)
|
||||||
|
{
|
||||||
|
return ProfileManager::main_thread_frameTimeLocalAvg(_durationCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // EASY_PROFILER_API_DISABLED
|
||||||
|
|
||||||
|
PROFILER_API profiler::timestamp_t now() { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t toNanoseconds(profiler::timestamp_t) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t toMicroseconds(profiler::timestamp_t) { return 0; }
|
||||||
|
|
||||||
|
PROFILER_API const profiler::BaseBlockDescriptor* registerDescription(profiler::EasyBlockStatus, const char*,
|
||||||
|
const char*, const char*, int,
|
||||||
|
profiler::block_type_t, profiler::color_t, bool)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const BaseBlockDescriptor*>(0xbad);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void endBlock() { }
|
||||||
|
PROFILER_API void setEnabled(bool) { }
|
||||||
|
PROFILER_API bool isEnabled() { return false; }
|
||||||
|
|
||||||
|
PROFILER_API void storeValue(const profiler::BaseBlockDescriptor*, profiler::DataType, const void*, uint16_t, bool,
|
||||||
|
profiler::ValueId)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void storeEvent(const profiler::BaseBlockDescriptor*, const char*) { }
|
||||||
|
PROFILER_API void storeBlock(const profiler::BaseBlockDescriptor*, const char*, profiler::timestamp_t,
|
||||||
|
profiler::timestamp_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PROFILER_API void beginBlock(profiler::Block&) { }
|
||||||
|
PROFILER_API void beginNonScopedBlock(const profiler::BaseBlockDescriptor*, const char*) { }
|
||||||
|
PROFILER_API uint32_t dumpBlocksToFile(const char*) { return 0; }
|
||||||
|
PROFILER_API const char* registerThreadScoped(const char*, profiler::ThreadGuard&) { return ""; }
|
||||||
|
PROFILER_API const char* registerThread(const char*) { return ""; }
|
||||||
|
PROFILER_API void setEventTracingEnabled(bool) { }
|
||||||
|
PROFILER_API bool isEventTracingEnabled() { return false; }
|
||||||
|
PROFILER_API void setLowPriorityEventTracing(bool) { }
|
||||||
|
PROFILER_API bool isLowPriorityEventTracing(bool) { return false; }
|
||||||
|
PROFILER_API void setContextSwitchLogFilename(const char*) { }
|
||||||
|
PROFILER_API const char* getContextSwitchLogFilename() { return ""; }
|
||||||
|
PROFILER_API void startListen(uint16_t) { }
|
||||||
|
PROFILER_API void stopListen() { }
|
||||||
|
PROFILER_API bool isListening() { return false; }
|
||||||
|
|
||||||
|
PROFILER_API bool isMainThread() { return false; }
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTime(profiler::Duration) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTimeLocalMax(profiler::Duration) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t this_thread_frameTimeLocalAvg(profiler::Duration) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTime(profiler::Duration) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTimeLocalMax(profiler::Duration) { return 0; }
|
||||||
|
PROFILER_API profiler::timestamp_t main_thread_frameTimeLocalAvg(profiler::Duration) { return 0; }
|
||||||
|
|
||||||
|
#endif // EASY_PROFILER_API_DISABLED
|
||||||
|
|
||||||
|
} // end extern "C".
|
@ -80,14 +80,18 @@
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
extern const uint32_t PROFILER_SIGNATURE;
|
extern const uint32_t EASY_PROFILER_SIGNATURE;
|
||||||
extern const uint32_t EASY_CURRENT_VERSION;
|
extern const uint32_t EASY_PROFILER_VERSION;
|
||||||
|
|
||||||
|
# define EASY_VERSION_INT(v_major, v_minor, v_patch) ((static_cast<uint32_t>(v_major) << 24) | \
|
||||||
|
(static_cast<uint32_t>(v_minor) << 16) | \
|
||||||
|
static_cast<uint32_t>(v_patch))
|
||||||
|
|
||||||
|
EASY_CONSTEXPR uint32_t MIN_COMPATIBLE_VERSION = EASY_VERSION_INT(0, 1, 0); ///< minimal compatible version (.prof file format was not changed seriously since this version)
|
||||||
|
EASY_CONSTEXPR uint32_t EASY_V_100 = EASY_VERSION_INT(1, 0, 0); ///< in v1.0.0 some additional data were added into .prof file
|
||||||
|
EASY_CONSTEXPR uint32_t EASY_V_130 = EASY_VERSION_INT(1, 3, 0); ///< in v1.3.0 changed sizeof(thread_id_t) uint32_t -> uint64_t
|
||||||
|
EASY_CONSTEXPR uint32_t EASY_V_200 = EASY_VERSION_INT(2, 0, 0); ///< in v2.0.0 file header was slightly rearranged
|
||||||
|
|
||||||
# define EASY_VERSION_INT(v_major, v_minor, v_patch) ((static_cast<uint32_t>(v_major) << 24) | (static_cast<uint32_t>(v_minor) << 16) | static_cast<uint32_t>(v_patch))
|
|
||||||
const uint32_t MIN_COMPATIBLE_VERSION = EASY_VERSION_INT(0, 1, 0); ///< minimal compatible version (.prof file format was not changed seriously since this version)
|
|
||||||
const uint32_t EASY_V_100 = EASY_VERSION_INT(1, 0, 0); ///< in v1.0.0 some additional data were added into .prof file
|
|
||||||
const uint32_t EASY_V_130 = EASY_VERSION_INT(1, 3, 0); ///< in v1.3.0 changed sizeof(thread_id_t) uint32_t -> uint64_t
|
|
||||||
const uint32_t EASY_V_200 = EASY_VERSION_INT(2, 0, 0); ///< in v2.0.0 file header was slightly rearranged
|
|
||||||
# undef EASY_VERSION_INT
|
# undef EASY_VERSION_INT
|
||||||
|
|
||||||
const uint64_t TIME_FACTOR = 1000000000ULL;
|
const uint64_t TIME_FACTOR = 1000000000ULL;
|
||||||
@ -120,7 +124,7 @@ const uint64_t TIME_FACTOR = 1000000000ULL;
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
inline bool isCompatibleVersion(uint32_t _version)
|
static bool isCompatibleVersion(uint32_t _version)
|
||||||
{
|
{
|
||||||
return _version >= MIN_COMPATIBLE_VERSION;
|
return _version >= MIN_COMPATIBLE_VERSION;
|
||||||
}
|
}
|
||||||
@ -243,24 +247,9 @@ namespace profiler {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifdef EASY_PROFILER_HASHED_CSTR_DEFINED
|
|
||||||
|
|
||||||
using StatsMap = std::unordered_map<profiler::block_id_t, profiler::BlockStatistics*, estd::hash<profiler::block_id_t> >;
|
|
||||||
|
|
||||||
/** \note It is absolutely safe to use hashed_cstr (which simply stores pointer) because std::unordered_map,
|
|
||||||
which uses it as a key, exists only inside fillTreesFromFile function. */
|
|
||||||
using IdMap = std::unordered_map<profiler::hashed_cstr, profiler::block_id_t>;
|
|
||||||
|
|
||||||
using CsStatsMap = std::unordered_map<profiler::hashed_cstr, profiler::BlockStatistics*>;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// TODO: Create optimized version of profiler::hashed_cstr for Linux too.
|
|
||||||
using StatsMap = std::unordered_map<profiler::block_id_t, profiler::BlockStatistics*, estd::hash<profiler::block_id_t> >;
|
using StatsMap = std::unordered_map<profiler::block_id_t, profiler::BlockStatistics*, estd::hash<profiler::block_id_t> >;
|
||||||
using IdMap = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
|
using IdMap = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
|
||||||
using CsStatsMap = std::unordered_map<profiler::hashed_stdstring, profiler::BlockStatistics*>;
|
using CsStatsMap = std::unordered_map<profiler::string_with_hash, profiler::BlockStatistics*>;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -438,7 +427,7 @@ struct EasyFileHeader
|
|||||||
uint32_t total_descriptors_number = 0;
|
uint32_t total_descriptors_number = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool readHeader_v1(EasyFileHeader& _header, std::istream& inFile, std::ostream& _log)
|
static bool readHeader_v1(EasyFileHeader& _header, std::istream& inFile, std::ostream& _log)
|
||||||
{
|
{
|
||||||
// File header before v2.0.0
|
// File header before v2.0.0
|
||||||
|
|
||||||
@ -491,7 +480,7 @@ bool readHeader_v1(EasyFileHeader& _header, std::istream& inFile, std::ostream&
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readHeader_v2(EasyFileHeader& _header, std::istream& inFile, std::ostream& _log)
|
static bool readHeader_v2(EasyFileHeader& _header, std::istream& inFile, std::ostream& _log)
|
||||||
{
|
{
|
||||||
// File header after v2.0.0
|
// File header after v2.0.0
|
||||||
|
|
||||||
@ -587,7 +576,7 @@ extern "C" PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<
|
|||||||
|
|
||||||
uint32_t signature = 0;
|
uint32_t signature = 0;
|
||||||
inFile.read((char*)&signature, sizeof(uint32_t));
|
inFile.read((char*)&signature, sizeof(uint32_t));
|
||||||
if (signature != PROFILER_SIGNATURE)
|
if (signature != EASY_PROFILER_SIGNATURE)
|
||||||
{
|
{
|
||||||
_log << "Wrong signature " << signature << "\nThis is not EasyProfiler file/stream.";
|
_log << "Wrong signature " << signature << "\nThis is not EasyProfiler file/stream.";
|
||||||
return 0;
|
return 0;
|
||||||
@ -1064,7 +1053,7 @@ extern "C" PROFILER_API bool readDescriptionsFromStream(std::atomic<int>& progre
|
|||||||
|
|
||||||
uint32_t signature = 0;
|
uint32_t signature = 0;
|
||||||
inFile.read((char*)&signature, sizeof(uint32_t));
|
inFile.read((char*)&signature, sizeof(uint32_t));
|
||||||
if (signature != PROFILER_SIGNATURE)
|
if (signature != EASY_PROFILER_SIGNATURE)
|
||||||
{
|
{
|
||||||
_log << "Wrong file signature.\nThis is not EasyProfiler file/stream.";
|
_log << "Wrong file signature.\nThis is not EasyProfiler file/stream.";
|
||||||
return false;
|
return false;
|
||||||
@ -1174,19 +1163,19 @@ struct BlocksAndCSwitchesRange
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void write(std::ostream& _stream, const char* _data, T _size)
|
static void write(std::ostream& _stream, const char* _data, T _size)
|
||||||
{
|
{
|
||||||
_stream.write(_data, _size);
|
_stream.write(_data, _size);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void write(std::ostream& _stream, const T& _data)
|
static void write(std::ostream& _stream, const T& _data)
|
||||||
{
|
{
|
||||||
_stream.write((const char*)&_data, sizeof(T));
|
_stream.write((const char*)&_data, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler::timestamp_t beginTime, profiler::timestamp_t endTime,
|
static BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler::timestamp_t beginTime,
|
||||||
const profiler::block_getter_fn& getter)
|
profiler::timestamp_t endTime, const profiler::block_getter_fn& getter)
|
||||||
{
|
{
|
||||||
const auto size = static_cast<profiler::block_index_t>(children.size());
|
const auto size = static_cast<profiler::block_index_t>(children.size());
|
||||||
BlocksRange range(size);
|
BlocksRange range(size);
|
||||||
@ -1226,11 +1215,11 @@ BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTree::children_t& children,
|
static BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTree::children_t& children,
|
||||||
const BlocksRange& range,
|
const BlocksRange& range,
|
||||||
const profiler::block_getter_fn& getter,
|
const profiler::block_getter_fn& getter,
|
||||||
const profiler::descriptors_list_t& descriptors,
|
const profiler::descriptors_list_t& descriptors,
|
||||||
bool contextSwitches)
|
bool contextSwitches)
|
||||||
{
|
{
|
||||||
BlocksMemoryAndCount memoryAndCount;
|
BlocksMemoryAndCount memoryAndCount;
|
||||||
|
|
||||||
@ -1275,9 +1264,9 @@ BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTre
|
|||||||
return memoryAndCount;
|
return memoryAndCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeBlocks(std::ostream& output, std::vector<char>& buffer, const profiler::BlocksTree::children_t& children,
|
static void serializeBlocks(std::ostream& output, std::vector<char>& buffer,
|
||||||
const BlocksRange& range, const profiler::block_getter_fn& getter,
|
const profiler::BlocksTree::children_t& children, const BlocksRange& range,
|
||||||
const profiler::descriptors_list_t& descriptors)
|
const profiler::block_getter_fn& getter, const profiler::descriptors_list_t& descriptors)
|
||||||
{
|
{
|
||||||
for (auto i = range.begin; i < range.end; ++i)
|
for (auto i = range.begin; i < range.end; ++i)
|
||||||
{
|
{
|
||||||
@ -1319,8 +1308,9 @@ void serializeBlocks(std::ostream& output, std::vector<char>& buffer, const prof
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeContextSwitches(std::ostream& output, std::vector<char>& buffer, const profiler::BlocksTree::children_t& children,
|
static void serializeContextSwitches(std::ostream& output, std::vector<char>& buffer,
|
||||||
const BlocksRange& range, const profiler::block_getter_fn& getter)
|
const profiler::BlocksTree::children_t& children, const BlocksRange& range,
|
||||||
|
const profiler::block_getter_fn& getter)
|
||||||
{
|
{
|
||||||
for (auto i = range.begin; i < range.end; ++i)
|
for (auto i = range.begin; i < range.end; ++i)
|
||||||
{
|
{
|
||||||
@ -1337,9 +1327,9 @@ void serializeContextSwitches(std::ostream& output, std::vector<char>& buffer, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeDescriptors(std::ostream& output, std::vector<char>& buffer,
|
static void serializeDescriptors(std::ostream& output, std::vector<char>& buffer,
|
||||||
const profiler::descriptors_list_t& descriptors,
|
const profiler::descriptors_list_t& descriptors,
|
||||||
profiler::block_id_t descriptors_count)
|
profiler::block_id_t descriptors_count)
|
||||||
{
|
{
|
||||||
const size_t size = std::min(descriptors.size(), static_cast<size_t>(descriptors_count));
|
const size_t size = std::min(descriptors.size(), static_cast<size_t>(descriptors_count));
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i)
|
||||||
@ -1461,8 +1451,8 @@ extern "C" PROFILER_API profiler::block_index_t writeTreesToStream(std::atomic<i
|
|||||||
const uint64_t usedMemorySizeDescriptors = serialized_descriptors.size() + descriptors_count * sizeof(uint16_t);
|
const uint64_t usedMemorySizeDescriptors = serialized_descriptors.size() + descriptors_count * sizeof(uint16_t);
|
||||||
|
|
||||||
// Write data to stream
|
// Write data to stream
|
||||||
write(str, PROFILER_SIGNATURE);
|
write(str, EASY_PROFILER_SIGNATURE);
|
||||||
write(str, EASY_CURRENT_VERSION);
|
write(str, EASY_PROFILER_VERSION);
|
||||||
write(str, pid);
|
write(str, pid);
|
||||||
|
|
||||||
// write 0 because we do not need to convert time from ticks to nanoseconds (it's already converted)
|
// write 0 because we do not need to convert time from ticks to nanoseconds (it's already converted)
|
||||||
|
68
easy_profiler_core/serialized_block.cpp
Normal file
68
easy_profiler_core/serialized_block.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
Lightweight profiler library for c++
|
||||||
|
Copyright(C) 2016-2018 Sergey Yagovtsev, Victor Zarubkin
|
||||||
|
|
||||||
|
Licensed under either of
|
||||||
|
* MIT license (LICENSE.MIT or http://opensource.org/licenses/MIT)
|
||||||
|
* Apache License, Version 2.0, (LICENSE.APACHE or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
The MIT License
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
The Apache License, Version 2.0 (the "License");
|
||||||
|
You may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <easy/serialized_block.h>
|
||||||
|
#include "thread_storage.h"
|
||||||
|
|
||||||
|
namespace profiler
|
||||||
|
{
|
||||||
|
|
||||||
|
SerializedBlock::SerializedBlock(const Block& block, uint16_t name_length)
|
||||||
|
: BaseBlockData(block)
|
||||||
|
{
|
||||||
|
char* pName = const_cast<char*>(name());
|
||||||
|
if (name_length != 0)
|
||||||
|
strncpy(pName, block.name(), name_length);
|
||||||
|
pName[name_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedCSwitch::SerializedCSwitch(const CSwitchBlock& block, uint16_t name_length)
|
||||||
|
: CSwitchEvent(block)
|
||||||
|
{
|
||||||
|
char* pName = const_cast<char*>(name());
|
||||||
|
if (name_length != 0)
|
||||||
|
strncpy(pName, block.name(), name_length);
|
||||||
|
pName[name_length] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace profiler.
|
Loading…
x
Reference in New Issue
Block a user