-
Tristan Walter authoredTristan Walter authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MemoryStats.cpp 10.98 KiB
#include "MemoryStats.h"
#include <misc/pretty.h>
#include <tracking/Tracker.h>
#include <misc/OutputLibrary.h>
namespace mem {
template <typename K, typename V>
uint64_t memory_selector(MemoryStats& stats, const std::map<K, V>& map, const std::string& name) {
//using map_t = typename remove_cvref<decltype(map)>::type;
uint64_t bytes = 0;//sizeof(map_t);
for (auto && [key, value] : map) {
bytes += stats.get_memory_size(value, name) + stats.get_memory_size(key, name);
}
return bytes;
}
template <typename K, typename V>
uint64_t memory_selector(MemoryStats& stats, const std::unordered_map<K, V>& map, const std::string& name) {
//using map_t = typename remove_cvref<decltype(map)>::type;
uint64_t bytes = 0;//sizeof(map_t);
for (auto && [key, value] : map) {
bytes += stats.get_memory_size(value, name) + stats.get_memory_size(key, name);
}
return bytes;
}
template <typename T, typename Q = std::less<T>>
uint64_t memory_selector(MemoryStats& stats, const std::set<T, Q>& obj, const std::string& name) {
uint64_t bytes = 0;//sizeof(std::set<T>);
for(auto && v : obj) {
bytes += stats.get_memory_size(v, name);
}
return bytes;
}
template <typename T, typename Q = std::less<T>>
uint64_t memory_selector(MemoryStats& stats, const std::unordered_set<T, Q>& obj, const std::string& name) {
uint64_t bytes = 0;//sizeof(std::set<T>);
for(auto && v : obj) {
bytes += stats.get_memory_size(v, name);
}
return bytes;
}
template <typename T>
uint64_t memory_selector(MemoryStats& stats, const std::vector<T>& obj, const std::string& name) {
uint64_t bytes = 0;//sizeof(std::set<T>);
for(auto && v : obj) {
bytes += stats.get_memory_size(v, name);
}
if(obj.capacity() > obj.size()) {
bytes += (obj.capacity() - obj.size()) * sizeof(T);
}
return bytes;
}
template <typename T>
uint64_t memory_selector(MemoryStats& stats, const std::deque<T>& obj, const std::string& name) {
uint64_t bytes = 0;//sizeof(std::set<T>);
for(auto && v : obj) {
bytes += stats.get_memory_size(v, name);
}
return bytes;
}
uint64_t memory_selector(MemoryStats& stats, const Individual::LocalCache& obj, const std::string& name) {
uint64_t bytes = 0;//sizeof(std::set<T>);
bytes += memory_selector(stats, obj._current_velocities, name);
bytes += memory_selector(stats, obj._v_samples, name);
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(std::string obj, const std::string&) {
return obj.capacity() + sizeof(std::string);
}
template <>
uint64_t MemoryStats::get_memory_size(MinimalOutline::Ptr obj, const std::string&) {
return (obj ? obj->memory_size() : 0);
}
template <>
uint64_t MemoryStats::get_memory_size(track::FrameProperties obj, const std::string& name) {
return memory_selector(*this, obj._pair_distances, name) + sizeof(track::FrameProperties);
}
template <>
uint64_t MemoryStats::get_memory_size(Image::Ptr obj, const std::string&) {
return (obj ? obj->size() : 0) + sizeof(Image) + sizeof(Image::Ptr);
}
template <>
uint64_t MemoryStats::get_memory_size(PhysicalProperties* obj, const std::string& ) {
uint64_t bytes = 0;
if(obj) {
bytes += sizeof(PhysicalProperties);
for(auto && v : obj->derivatives())
bytes += v->memory_size();
}
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(pv::BlobPtr obj, const std::string& ) {
uint64_t bytes = 0;
if(obj) {
bytes += sizeof(pv::Blob);
if(obj->pixels()) bytes += obj->pixels()->size() * sizeof(typename cmn::remove_cvref<decltype(*obj->pixels())>::type::value_type);
bytes += obj->hor_lines().size() * sizeof(typename cmn::remove_cvref<decltype(obj->hor_lines())>::type::value_type);
}
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(pv::CompressedBlob obj, const std::string& ) {
uint64_t bytes = 0;
bytes += obj.lines.capacity() * sizeof(decltype(pv::CompressedBlob::lines)::value_type);
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(Midline::Ptr obj, const std::string& name) {
uint64_t bytes = 0;
if(obj) {
bytes += sizeof(Midline);
details[name]["class"] += sizeof(Midline);
bytes += obj->segments().size() * sizeof(cmn::remove_cvref<decltype(obj->segments())>::type::value_type);
details[name]["segments"] += obj->segments().size() * sizeof(cmn::remove_cvref<decltype(obj->segments())>::type::value_type);
}
return bytes;
}
#define _ADD_DETAIL(NAME) { auto by = get_memory_size(obj-> NAME, name); details[name][ #NAME ] += by; bytes += by; }
template <>
uint64_t MemoryStats::get_memory_size(std::shared_ptr<Individual::BasicStuff> obj, const std::string& name) {
uint64_t bytes = sizeof(obj)
+ sizeof(Individual::BasicStuff);
_ADD_DETAIL(centroid)
//_ADD_DETAIL(weighted_centroid)
_ADD_DETAIL(blob)
if(obj->pixels)
_ADD_DETAIL(pixels)
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(std::shared_ptr<Individual::PostureStuff> obj, const std::string& name) {
uint64_t bytes = sizeof(obj)
+ sizeof(Individual::PostureStuff);
_ADD_DETAIL(outline)
_ADD_DETAIL(head)
_ADD_DETAIL(centroid_posture)
_ADD_DETAIL(cached_pp_midline)
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(std::shared_ptr<Individual::SegmentInformation> obj, const std::string& name) {
uint64_t bytes = sizeof(obj)
+ sizeof(Individual::SegmentInformation)
+ memory_selector(*this, obj->basic_index, name)
+ memory_selector(*this, obj->posture_index, name);
return bytes;
}
template <>
uint64_t MemoryStats::get_memory_size(std::vector<Individual*> obj, const std::string& name) {
return memory_selector(*this, obj, name);
}
template <>
uint64_t MemoryStats::get_memory_size(FOI foi, const std::string& ) {
return sizeof(foi) + foi.description().capacity();
}
template <>
uint64_t MemoryStats::get_memory_size(std::map<long_t, std::pair<void*, std::function<void(void*)>>> obj, const std::string& name) {
for(auto && [key, value] : obj) {
details[name][Meta::toStr(key)] += sizeof(decltype(obj)::value_type);
}
return sizeof(decltype(obj)::value_type) * obj.size();
}
MemoryStats::MemoryStats() : id(-1), bytes(0) {
}
#define IND_BYTE_SIZE(X) this->sizes[ #X ] = calculate_byte_size(fish-> X, #X )
TrackerMemoryStats::TrackerMemoryStats() {
auto fish = Tracker::instance();
auto calculate_byte_size = [&](const auto& map, const std::string& name) {
uint64_t summary = memory_selector(*this, map, name);
bytes += summary;
return summary;
};
IND_BYTE_SIZE(_statistics);
IND_BYTE_SIZE(_added_frames);
IND_BYTE_SIZE(_consecutive);
IND_BYTE_SIZE(_active_individuals_frame);
IND_BYTE_SIZE(_individuals);
IND_BYTE_SIZE(_active_individuals);
IND_BYTE_SIZE(_inactive_individuals);
auto fois = FOI::all_fois();
uint64_t foi_bytes = sizeof(decltype(fois));
for(auto && [id, set] : fois) {
auto name = FOI::name(id);
auto b = memory_selector(*this, set, "fois");
foi_bytes += b;
details["fois"][name] += b;
}
sizes["fois"] = foi_bytes;
bytes += foi_bytes;
id = -2;
}
IndividualMemoryStats::IndividualMemoryStats(Individual *fish) {
if(!fish)
return;
auto calculate_byte_size = [&](const auto& map, const std::string& name) {
uint64_t summary = memory_selector(*this, map, name);
bytes += summary;
return summary;
};
bytes = sizeof(Individual);
sizes["misc"] = bytes;
//IND_BYTE_SIZE(_centroid);
//IND_BYTE_SIZE(_head);
//IND_BYTE_SIZE(_centroid_posture);
//IND_BYTE_SIZE(_weighted_centroid);
IND_BYTE_SIZE(_basic_stuff);
IND_BYTE_SIZE(_posture_stuff);
//IND_BYTE_SIZE(_thresholded_size);
IND_BYTE_SIZE(automatically_matched);
IND_BYTE_SIZE(_local_cache);
//bytes += fish->automatically_matched.size() * sizeof(decltype(fish->automatically_matched)::value_type);
//IND_BYTE_SIZE(_posture_original_angles);
//IND_BYTE_SIZE(_blobs);
IND_BYTE_SIZE(_frame_segments);
// posture stuff
//IND_BYTE_SIZE(_midlines);
//IND_BYTE_SIZE(_cached_pp_midlines);
//IND_BYTE_SIZE(_cached_fixed_midlines);
//IND_BYTE_SIZE(_outlines);
// recognition stuff
IND_BYTE_SIZE(_training_data);
IND_BYTE_SIZE(_recognition_segments);
//IND_BYTE_SIZE(average_recognition_segment);
//IND_BYTE_SIZE(average_processed_segment);
IND_BYTE_SIZE(_average_recognition);
// other / gui stuff
IND_BYTE_SIZE(_delete_callbacks);
IND_BYTE_SIZE(_custom_data);
id = fish->identity().ID();
}
OutputLibraryMemoryStats::OutputLibraryMemoryStats(Output::LibraryCache::Ptr ptr) {
auto cache = ptr ? ptr : Output::LibraryCache::default_cache();
if(cache) {
bytes += sizeof(decltype(cache->_cache)::value_type) * cache->_cache.size();
for(auto && [fish, frames_fields] : cache->_cache) {
bytes += sizeof(decltype(frames_fields)::value_type) * frames_fields.size();
for(auto && [frame, fields_modifiers] : frames_fields) {
bytes += sizeof(decltype(fields_modifiers)::value_type) * fields_modifiers.size();
for(auto && [field, modifiers_values] : fields_modifiers) {
bytes += field.capacity();
bytes += sizeof(decltype(modifiers_values)::value_type) * modifiers_values.size();
/*for(auto && [modifier, value] : modifiers_values) {
}*/
}
}
}
sizes["output_cache"] = bytes;
}
bytes += sizeof(decltype(cache)::element_type);
id = -2;
}
void IndividualMemoryStats::print() const {
DebugHeader("IndividualMemoryStats");
MemoryStats::print();
}
void TrackerMemoryStats::print() const {
DebugHeader("TrackerMemoryStats");
MemoryStats::print();
}
void OutputLibraryMemoryStats::print() const {
DebugHeader("OutputLibraryMemoryStats");
MemoryStats::print();
}
void MemoryStats::print() const {
std::set<std::string, std::function<bool(const std::string&, const std::string&)>> sorted([this](const std::string& A, const std::string& B) -> bool {
return this->sizes.at(A) > this->sizes.at(B) || (this->sizes.at(A) == this->sizes.at(B) && A > B);
});
for(auto && [key, value] : this->sizes)
sorted.insert(key);
std::vector<std::tuple<std::string, FileSize>> vec;
for(auto &key : sorted)
vec.push_back({key, FileSize{sizes.at(key)}});
auto str = prettify_array(Meta::toStr(vec));
auto overall = Meta::toStr(FileSize{bytes});
auto id_str = id == -2 ? std::string("overall") : (id == -1 ? "<empty>" : Meta::toStr(id));
Debug("%S: %S\n%S", &id_str, &overall, &str);
}
}