mirror of
https://github.com/yse/easy_profiler.git
synced 2024-12-26 08:01:51 +08:00
#0 [Core] refactoring
This commit is contained in:
parent
745609f1a4
commit
8c90ee7ef5
@ -112,16 +112,21 @@ message(STATUS "")
|
||||
#################################################
|
||||
# Add source files:
|
||||
set(CPP_FILES
|
||||
base_block_descriptor.cpp
|
||||
block.cpp
|
||||
block_descriptor.cpp
|
||||
easy_socket.cpp
|
||||
event_trace_win.cpp
|
||||
nonscoped_block.cpp
|
||||
profile_manager.cpp
|
||||
profiler.cpp
|
||||
reader.cpp
|
||||
serialized_block.cpp
|
||||
thread_storage.cpp
|
||||
)
|
||||
|
||||
set(H_FILES
|
||||
block_descriptor.h
|
||||
chunk_allocator.h
|
||||
current_time.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 <cstring>
|
||||
#include "outstream.h"
|
||||
#include <ostream>
|
||||
#include "alignment_helpers.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -261,7 +261,7 @@ public:
|
||||
|
||||
\warning Data will be cleared after serialization.
|
||||
*/
|
||||
void serialize(profiler::OStream& _outputStream)
|
||||
void serialize(std::ostream& _outputStream)
|
||||
{
|
||||
// Chunks are stored in reversed order (stack).
|
||||
// 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 {
|
||||
|
||||
class hashed_stdstring
|
||||
@ -292,6 +152,155 @@ 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
|
||||
|
||||
#include "spin_lock.h"
|
||||
#include "outstream.h"
|
||||
#include "hashed_cstr.h"
|
||||
#include "thread_storage.h"
|
||||
#include "current_time.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -69,7 +70,9 @@ using processid_t = uint64_t;
|
||||
|
||||
class BlockDescriptor;
|
||||
|
||||
namespace profiler { class ValueId; }
|
||||
namespace profiler {
|
||||
class ValueId;
|
||||
}
|
||||
|
||||
class ProfileManager
|
||||
{
|
||||
@ -79,23 +82,27 @@ class ProfileManager
|
||||
|
||||
ProfileManager();
|
||||
|
||||
using atomic_timestamp_t = std::atomic<profiler::timestamp_t>;
|
||||
using guard_lock_t = profiler::guard_lock<profiler::spin_lock>;
|
||||
using atomic_timestamp_t = std::atomic<profiler::timestamp_t>;
|
||||
using guard_lock_t = profiler::guard_lock<profiler::spin_lock>;
|
||||
using map_of_threads_stacks = std::map<profiler::thread_id_t, ThreadStorage>;
|
||||
using block_descriptors_t = std::vector<BlockDescriptor*>;
|
||||
|
||||
#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
|
||||
using block_descriptors_t = std::vector<BlockDescriptor*>;
|
||||
using descriptors_map_t = std::unordered_map<profiler::string_with_hash, profiler::block_id_t>;
|
||||
|
||||
const processid_t m_processId;
|
||||
|
||||
#if defined(EASY_CHRONO_CLOCK) || defined(_WIN32)
|
||||
const int64_t m_cpuFrequency;
|
||||
#endif
|
||||
|
||||
map_of_threads_stacks m_threads;
|
||||
block_descriptors_t m_descriptors;
|
||||
descriptors_map_t m_descriptorsMap;
|
||||
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_endTime;
|
||||
atomic_timestamp_t m_frameMax;
|
||||
@ -114,13 +121,8 @@ class ProfileManager
|
||||
|
||||
std::string m_csInfoFilename = "/tmp/cs_profiling_info.log";
|
||||
|
||||
uint32_t dumpBlocksToStream(profiler::OStream& _outputStream, bool _lockSpin, bool _async);
|
||||
void setBlockStatus(profiler::block_id_t _id, profiler::EasyBlockStatus _status);
|
||||
|
||||
std::thread m_listenThread;
|
||||
void listen(uint16_t _port);
|
||||
|
||||
std::atomic_bool m_stopListen;
|
||||
std::thread m_listenThread;
|
||||
std::atomic_bool m_stopListen;
|
||||
|
||||
public:
|
||||
|
||||
@ -147,6 +149,7 @@ public:
|
||||
void beginBlock(profiler::Block& _block);
|
||||
void beginNonScopedBlock(const profiler::BaseBlockDescriptor* _desc, const char* _runtimeName);
|
||||
void endBlock();
|
||||
|
||||
profiler::timestamp_t maxFrameDuration();
|
||||
profiler::timestamp_t avgFrameDuration();
|
||||
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);
|
||||
|
||||
void setContextSwitchLogFilename(const char* name)
|
||||
{
|
||||
m_csInfoFilename = name;
|
||||
}
|
||||
|
||||
const char* getContextSwitchLogFilename() const
|
||||
{
|
||||
return m_csInfoFilename.c_str();
|
||||
}
|
||||
void setContextSwitchLogFilename(const char* name);
|
||||
const char* getContextSwitchLogFilename() const;
|
||||
|
||||
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);
|
||||
@ -178,8 +174,24 @@ public:
|
||||
void stopListen();
|
||||
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:
|
||||
|
||||
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 beginFrame();
|
||||
@ -196,13 +208,13 @@ private:
|
||||
ThreadStorage& _threadStorage(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);
|
||||
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);
|
||||
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_CURRENT_VERSION;
|
||||
extern const uint32_t EASY_PROFILER_SIGNATURE;
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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 IdMap = std::unordered_map<profiler::hashed_stdstring, profiler::block_id_t>;
|
||||
using CsStatsMap = std::unordered_map<profiler::hashed_stdstring, profiler::BlockStatistics*>;
|
||||
|
||||
#endif
|
||||
using CsStatsMap = std::unordered_map<profiler::string_with_hash, profiler::BlockStatistics*>;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -438,7 +427,7 @@ struct EasyFileHeader
|
||||
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
|
||||
|
||||
@ -491,7 +480,7 @@ bool readHeader_v1(EasyFileHeader& _header, std::istream& inFile, std::ostream&
|
||||
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
|
||||
|
||||
@ -587,7 +576,7 @@ extern "C" PROFILER_API profiler::block_index_t fillTreesFromStream(std::atomic<
|
||||
|
||||
uint32_t signature = 0;
|
||||
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.";
|
||||
return 0;
|
||||
@ -1064,7 +1053,7 @@ extern "C" PROFILER_API bool readDescriptionsFromStream(std::atomic<int>& progre
|
||||
|
||||
uint32_t signature = 0;
|
||||
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.";
|
||||
return false;
|
||||
@ -1174,19 +1163,19 @@ struct BlocksAndCSwitchesRange
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler::timestamp_t beginTime, profiler::timestamp_t endTime,
|
||||
const profiler::block_getter_fn& getter)
|
||||
static BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler::timestamp_t beginTime,
|
||||
profiler::timestamp_t endTime, const profiler::block_getter_fn& getter)
|
||||
{
|
||||
const auto size = static_cast<profiler::block_index_t>(children.size());
|
||||
BlocksRange range(size);
|
||||
@ -1226,11 +1215,11 @@ BlocksRange findRange(const profiler::BlocksTree::children_t& children, profiler
|
||||
return range;
|
||||
}
|
||||
|
||||
BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTree::children_t& children,
|
||||
const BlocksRange& range,
|
||||
const profiler::block_getter_fn& getter,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
bool contextSwitches)
|
||||
static BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTree::children_t& children,
|
||||
const BlocksRange& range,
|
||||
const profiler::block_getter_fn& getter,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
bool contextSwitches)
|
||||
{
|
||||
BlocksMemoryAndCount memoryAndCount;
|
||||
|
||||
@ -1275,9 +1264,9 @@ BlocksMemoryAndCount calculateUsedMemoryAndBlocksCount(const profiler::BlocksTre
|
||||
return memoryAndCount;
|
||||
}
|
||||
|
||||
void serializeBlocks(std::ostream& output, std::vector<char>& buffer, const profiler::BlocksTree::children_t& children,
|
||||
const BlocksRange& range, const profiler::block_getter_fn& getter,
|
||||
const profiler::descriptors_list_t& descriptors)
|
||||
static void serializeBlocks(std::ostream& output, std::vector<char>& buffer,
|
||||
const profiler::BlocksTree::children_t& children, const BlocksRange& range,
|
||||
const profiler::block_getter_fn& getter, const profiler::descriptors_list_t& descriptors)
|
||||
{
|
||||
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,
|
||||
const BlocksRange& range, const profiler::block_getter_fn& getter)
|
||||
static void serializeContextSwitches(std::ostream& output, std::vector<char>& buffer,
|
||||
const profiler::BlocksTree::children_t& children, const BlocksRange& range,
|
||||
const profiler::block_getter_fn& getter)
|
||||
{
|
||||
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,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_t descriptors_count)
|
||||
static void serializeDescriptors(std::ostream& output, std::vector<char>& buffer,
|
||||
const profiler::descriptors_list_t& descriptors,
|
||||
profiler::block_id_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)
|
||||
@ -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);
|
||||
|
||||
// Write data to stream
|
||||
write(str, PROFILER_SIGNATURE);
|
||||
write(str, EASY_CURRENT_VERSION);
|
||||
write(str, EASY_PROFILER_SIGNATURE);
|
||||
write(str, EASY_PROFILER_VERSION);
|
||||
write(str, pid);
|
||||
|
||||
// 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