mem tracing compile time option, simplify by MemoryTracer as member

This commit is contained in:
Christopher Lackner 2020-11-21 15:49:07 +01:00
parent a394ffedef
commit a69cdc9000
13 changed files with 142 additions and 100 deletions

View File

@ -33,6 +33,7 @@ option( BUILD_STUB_FILES "Build stub files for better autocompletion" ON)
option( BUILD_FOR_CONDA "Link python libraries only to executables" OFF)
option( USE_SUPERBUILD "use ccache" ON)
option( TRACE_MEMORY "Enable memory tracing" OFF)
set(NG_COMPILE_FLAGS "" CACHE STRING "Additional compile flags")

View File

@ -143,6 +143,7 @@ set_vars( NETGEN_CMAKE_ARGS
USE_SPDLOG
DEBUG_LOG
CHECK_RANGE
TRACE_MEMORY
BUILD_STUB_FILES
BUILD_FOR_CONDA
NG_COMPILE_FLAGS

View File

@ -42,6 +42,11 @@ if(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL
target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE)
endif(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
if(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
target_compile_definitions(ngcore PUBLIC NETGEN_TRACE_MEMORY)
endif(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
if(USE_SPDLOG)
include_directories(${SPDLOG_INCLUDE_DIR})
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}

View File

@ -655,7 +655,6 @@ namespace ngcore
/// that's the data we have to delete, nullptr for not owning the memory
T * mem_to_delete;
int mem_tracing_id = 0;
using FlatArray<T,IndexType>::size;
using FlatArray<T,IndexType>::data;
@ -701,7 +700,7 @@ namespace ngcore
NETGEN_INLINE Array (Array && a2)
{
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, a2.mem_tracing_id, sizeof(T)*a2.allocsize);
mt.Swap(sizeof(T) * allocsize, a2.mt, sizeof(T) * a2.allocsize);
size = a2.size;
data = a2.data;
@ -774,7 +773,7 @@ namespace ngcore
NETGEN_INLINE ~Array()
{
delete [] mem_to_delete;
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
mt.Free(sizeof(T)*allocsize);
}
// Only provide this function if T is archivable
@ -829,7 +828,7 @@ namespace ngcore
NETGEN_INLINE const Array & Assign (size_t asize, LocalHeap & lh)
{
delete [] mem_to_delete;
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
mt.Free(sizeof(T)*allocsize);
size = allocsize = asize;
data = lh.Alloc<T> (asize);
mem_to_delete = nullptr;
@ -937,7 +936,7 @@ namespace ngcore
NETGEN_INLINE void DeleteAll ()
{
delete [] mem_to_delete;
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
mt.Free(sizeof(T)*allocsize);
mem_to_delete = NULL;
data = 0;
size = allocsize = 0;
@ -969,7 +968,7 @@ namespace ngcore
/// steal array
NETGEN_INLINE Array & operator= (Array && a2)
{
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, a2.mem_tracing_id, sizeof(T)*a2.allocsize);
mt.Swap(sizeof(T)*allocsize, a2.mt, sizeof(T)*a2.allocsize);
ngcore::Swap (size, a2.size);
ngcore::Swap (data, a2.data);
@ -1044,7 +1043,7 @@ namespace ngcore
NETGEN_INLINE void Swap (Array & b)
{
TraceMemorySwap(mem_tracing_id, sizeof(T)*allocsize, b.mem_tracing_id, sizeof(T)*b.allocsize);
mt.Swap(sizeof(T) * allocsize, b.mt, sizeof(T) * b.allocsize);
ngcore::Swap (size, b.size);
ngcore::Swap (data, b.data);
@ -1052,21 +1051,18 @@ namespace ngcore
ngcore::Swap (mem_to_delete, b.mem_to_delete);
}
NETGEN_INLINE void SetMemoryTracing (int mem_id)
NETGEN_INLINE void StartMemoryTracing () const
{
if(!mem_tracing_id && mem_id)
TraceMemoryAlloc(mem_id, sizeof(T)*allocsize);
if(mem_tracing_id && !mem_id)
TraceMemoryFree(mem_tracing_id, sizeof(T)*allocsize);
mem_tracing_id = mem_id;
mt.Alloc(sizeof(T) * allocsize);
}
const MemoryTracer& GetMemoryTracer() const { return mt; }
private:
/// resize array, at least to size minsize. copy contents
NETGEN_INLINE void ReSize (size_t minsize);
MemoryTracer mt;
};
@ -1079,7 +1075,7 @@ namespace ngcore
T * hdata = data;
data = new T[nsize];
TraceMemoryAlloc(mem_tracing_id, sizeof(T)*nsize );
mt.Alloc(sizeof(T) * nsize);
if (hdata)
{
@ -1093,7 +1089,7 @@ namespace ngcore
for (size_t i = 0; i < mins; i++) data[i] = std::move(hdata[i]);
#endif
delete [] mem_to_delete;
TraceMemoryFree( mem_tracing_id, sizeof(T)*allocsize );
mt.Free(sizeof(T) * allocsize);
}
mem_to_delete = data;

View File

@ -36,10 +36,15 @@ namespace ngcore
void BitArray :: SetSize (size_t asize)
{
if (size == asize) return;
if (owns_data) delete [] data;
if (owns_data)
{
delete [] data;
mt.Free(Addr(size)+1);
}
size = asize;
data = new unsigned char [Addr (size)+1];
mt.Alloc(Addr(size)+1);
}
BitArray & BitArray :: Set () throw()

View File

@ -150,6 +150,14 @@ public:
NGCORE_API void DoArchive(Archive& archive);
NGCORE_API auto * Data() const { return data; }
const MemoryTracer& GetMemoryTracer() const { return mt; }
void StartMemoryTracing() const
{
if(owns_data)
mt.Alloc(Addr(size)+1);
}
private:
///
unsigned char Mask (size_t i) const
@ -159,6 +167,7 @@ private:
size_t Addr (size_t i) const
{ return (i / CHAR_BIT); }
MemoryTracer mt;
};

View File

@ -743,7 +743,9 @@ namespace ngcore
}
}
WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
WriteMemoryChart("");
#endif // NETGEN_TRACE_MEMORY
paje.WriteEvents();
}
@ -930,6 +932,7 @@ namespace ngcore
}
#ifdef NETGEN_TRACE_MEMORY
void PajeTrace::WriteMemoryChart( std::string fname )
{
if(fname=="")
@ -1053,6 +1056,7 @@ namespace ngcore
WriteSunburstHTML( root, fname, false );
}
#endif // NETGEN_TRACE_MEMORY
void PajeTrace::WriteTimingChart( )
{

View File

@ -31,7 +31,9 @@ namespace ngcore
public:
NGCORE_API void WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
NGCORE_API void WriteMemoryChart( std::string fname );
#endif // NETGEN_TRACE_MEMORY
// Approximate number of events to trace. Tracing will
// be stopped if any thread reaches this number of events

View File

@ -113,7 +113,9 @@ namespace ngcore
NgProfiler prof; // NOLINT
#ifdef NETGEN_TRACE_MEMORY
std::vector<std::string> MemoryTracer::names{"root"};
std::map< int, std::vector<int> > MemoryTracer::tree;
#endif // NETGEN_TRACE_MEMORY
} // namespace ngcore

View File

@ -304,45 +304,29 @@ namespace ngcore
namespace detail
{
//Type trait to check if a class implements a 'const MemoryTracer& GetMemoryTracer()' function
template<typename T>
struct has_GetMemoryTracer
{
private:
template<typename T2>
static constexpr auto check(T2*) ->
typename std::is_same<decltype(std::declval<T2>().GetMemoryTracer()),const MemoryTracer &>::type;
template<typename>
static constexpr std::false_type check(...);
using type = decltype(check<T>(nullptr)); // NOLINT
public:
static constexpr bool value = type::value;
};
//Type trait to check if a class implements a 'void SetMemoryTacing(int)' function
template<typename T>
struct has_SetMemoryTracing
struct has_StartMemoryTracing
{
private:
template<typename T2>
static constexpr auto check(T2*) ->
typename std::is_same<decltype(std::declval<T2>().SetMemoryTracing(0)),void>::type;
typename std::is_same<decltype(std::declval<T2>().StartMemoryTracing()),void>::type;
template<typename>
static constexpr std::false_type check(...);
using type = decltype(check<T>(nullptr)); // NOLINT
public:
static constexpr bool value = type::value;
};
} // namespace detail
class MemoryTracer
{
#ifdef NETGEN_TRACE_MEMORY
NGCORE_API static std::vector<std::string> names;
NGCORE_API static std::map< int, std::vector<int> > tree;
static int GetId(std::string name)
static int CreateId(const std::string& name)
{
int id = names.size();
names.push_back(name);
@ -350,48 +334,73 @@ namespace ngcore
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
return id;
}
int id;
public:
MemoryTracer( std::string name )
{
id = GetId(name);
id = CreateId(name);
}
// not tracing
MemoryTracer() : id(0) {}
template <typename... TRest>
MemoryTracer( std::string name, TRest & ... rest )
{
id = GetId(name);
id = CreateId(name);
Track(rest...);
}
NETGEN_INLINE void Alloc(size_t size) const
{
if(id && trace)
trace->AllocMemory(id, size);
}
void Free(size_t size) const
{
if(id && trace)
trace->FreeMemory(id, size);
}
void Swap(size_t mysize, MemoryTracer& other, size_t other_size) const
{
if(!trace || (id == 0 && other.id == 0))
return;
if(id == 0)
return trace->ChangeMemory(other.id, mysize - other_size);
if(other.id == 0)
return trace->ChangeMemory(id, other_size - mysize);
// first decrease memory, otherwise have artificial/wrong high peak memory usage
if(mysize<other_size)
{
trace->ChangeMemory(other.id, mysize-other_size);
trace->ChangeMemory(id, other_size-mysize);
}
else
{
trace->ChangeMemory(id, other_size-mysize);
trace->ChangeMemory(other.id, mysize-other_size);
}
}
int GetId() const { return id; }
template <typename T1, typename... TRest>
void Track( T1 & obj, std::string name, TRest & ... rest ) const
void Track( T1 & obj, const std::string& name, TRest & ... rest ) const
{
Track(obj, name);
Track(rest...);
}
template<typename T>
void Track( T & obj, std::string name ) const
void Track( T & obj, const std::string& name ) const
{
if constexpr(detail::has_SetMemoryTracing<T>::value)
{
int child_id = GetId(name);
tree[id].push_back(child_id);
obj.SetMemoryTracing(child_id);
}
if constexpr(detail::has_GetMemoryTracer<T>::value)
{
auto & mt = obj.GetMemoryTracer();
int child_id = mt.id;
if(name!="")
names[mt.id] = name;
tree[id].push_back(child_id);
}
obj.GetMemoryTracer().Activate(obj, name);
tree[id].push_back(obj.GetMemoryTracer().GetId());
}
static std::string GetName(int id)
@ -404,7 +413,20 @@ namespace ngcore
return names[id];
}
void SetName(std::string name) const
template<typename T>
void Activate(T& me, const std::string& name) const
{
if(!id)
{
const_cast<MemoryTracer*>(this)->id = CreateId(name);
if constexpr(detail::has_StartMemoryTracing<T>::value)
me.StartMemoryTracing();
}
else
SetName(name);
}
void SetName(const std::string& name) const
{
names[id] = name;
}
@ -412,49 +434,26 @@ namespace ngcore
static const std::vector<std::string> & GetNames() { return names; }
static const std::map<int, std::vector<int>> & GetTree() { return tree; }
#else // NETGEN_TRACE_MEMORY
public:
MemoryTracer() {}
MemoryTracer( std::string name ) {}
template <typename... TRest>
MemoryTracer( std::string name, TRest & ... ) {}
void Alloc(size_t size) const {}
void Free(size_t size) const {}
void Swap(...) const {}
int GetId() const { return 0; }
template <typename... TRest>
void Track(TRest&...) const {}
static std::string GetName(int id) { return ""; }
std::string GetName() const { return ""; }
void SetName(std::string name) const {}
#endif // NETGEN_TRACE_MEMORY
};
NETGEN_INLINE void TraceMemoryAlloc( int mem_id, size_t size )
{
if(mem_id && trace)
trace->AllocMemory(mem_id, size);
}
NETGEN_INLINE void TraceMemoryFree( int mem_id, size_t size )
{
if(mem_id && trace)
trace->FreeMemory(mem_id, size);
}
NETGEN_INLINE void TraceMemoryChange( int mem_id, long long size )
{
if(mem_id && trace)
trace->ChangeMemory(mem_id, size);
}
NETGEN_INLINE void TraceMemorySwap( int mem_id, size_t size, int mem_id2, size_t size2 )
{
if(!trace || (mem_id==0 && mem_id2==0))
return;
if(mem_id == 0)
return trace->ChangeMemory(mem_id2, size-size2);
if(mem_id2 == 0)
return trace->ChangeMemory(mem_id, size2-size);
// first decrease memory, otherwise have artificial/wrong high peak memory usage
if(size<size2)
{
trace->ChangeMemory(mem_id2, size-size2);
trace->ChangeMemory(mem_id, size2-size);
}
else
{
trace->ChangeMemory(mem_id, size2-size);
trace->ChangeMemory(mem_id2, size-size2);
}
}
} // namespace ngcore
// Helper macro to easily add multiple timers in a function for profiling

View File

@ -266,7 +266,9 @@ threads : int
.def_static("SetTraceThreads", &PajeTrace::SetTraceThreads)
.def_static("SetTraceThreadCounter", &PajeTrace::SetTraceThreadCounter)
.def_static("SetMaxTracefileSize", &PajeTrace::SetMaxTracefileSize)
#ifdef NETGEN_TRACE_MEMORY
.def_static("WriteMemoryChart", [](string filename){ if(trace) trace->WriteMemoryChart(filename); }, py::arg("filename")="memory" )
#endif // NETGEN_TRACE_MEMORY
;

View File

@ -159,6 +159,7 @@ namespace ngcore
NETGEN_INLINE Table (Table && tab2)
: FlatTable<T,IndexType>(0, nullptr, nullptr)
{
tab2.mt.Free(tab2.GetMemUsage());
Swap (size, tab2.size);
Swap (index, tab2.index);
Swap (data, tab2.data);
@ -166,6 +167,7 @@ namespace ngcore
NETGEN_INLINE Table & operator= (Table && tab2)
{
mt.Swap(GetMemUsage(), tab2.mt, tab2.GetMemUsage());
Swap (size, tab2.size);
Swap (index, tab2.index);
Swap (data, tab2.data);
@ -177,6 +179,7 @@ namespace ngcore
/// Delete data
NETGEN_INLINE ~Table ()
{
mt.Free(GetMemUsage());
delete [] data;
delete [] index;
}
@ -188,6 +191,16 @@ namespace ngcore
NETGEN_INLINE size_t NElements() const { return index[size]; }
using FlatTable<T,IndexType>::operator[];
NETGEN_INLINE void StartMemoryTracing (int mem_id)
{
mt.Alloc(GetMemUsage());
}
const MemoryTracer& GetMemoryTracer() const { return mt; }
private:
size_t GetMemUsage() const { return size == 0 ? 0 : sizeof(T)*index[size] + sizeof(IndexType) * size+1; }
MemoryTracer mt;
};

View File

@ -90,6 +90,9 @@ namespace netgen
void GenerateBoundaryLayer(Mesh& mesh, const BoundaryLayerParameters& blp)
{
static Timer timer("Create Boundarylayers");
RegionTimer regt(timer);
int max_edge_nr = -1;
for(const auto& seg : mesh.LineSegments())
if(seg.edgenr > max_edge_nr)