diff options
Diffstat (limited to 'runtime/contrib/heap_trace/src')
-rw-r--r-- | runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc | 44 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/cl_release_mem_object.cc | 43 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/free_stub.cc | 35 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/function_resolver.h | 29 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/malloc_stub.cc | 39 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/realloc_stub.cc | 40 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/symbol_searcher.cc | 82 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/symbol_searcher.h | 22 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/trace.cc | 103 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/trace.h | 75 | ||||
-rw-r--r-- | runtime/contrib/heap_trace/src/valloc_stub.cc | 39 |
11 files changed, 551 insertions, 0 deletions
diff --git a/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc b/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc new file mode 100644 index 000000000..d9d2700ee --- /dev/null +++ b/runtime/contrib/heap_trace/src/cl_create_buffer_stub.cc @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <CL/cl.h> + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +cl_mem clCreateBuffer(cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, + cl_int *errcode_ret) +{ + static auto isOriginalFunctionCallSuccessful = [](cl_mem result) -> bool { return result; }; + + static auto originalFunction = + findFunctionByName<cl_mem, cl_context, cl_mem_flags, size_t, void *, cl_int *>( + "clCreateBuffer"); + cl_mem result = originalFunction(context, flags, size, host_ptr, errcode_ret); + if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive()) + { + GlobalTrace->logAllocationEvent(result, size); + } + + return result; +} +} diff --git a/runtime/contrib/heap_trace/src/cl_release_mem_object.cc b/runtime/contrib/heap_trace/src/cl_release_mem_object.cc new file mode 100644 index 000000000..f2f249e0b --- /dev/null +++ b/runtime/contrib/heap_trace/src/cl_release_mem_object.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <CL/cl.h> + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +cl_int clReleaseMemObject(cl_mem mem) +{ + static auto isOriginalFunctionCallSuccessful = [](cl_int result) -> bool { + return result == CL_SUCCESS; + }; + + auto originalFunction = findFunctionByName<cl_int, cl_mem>("clReleaseMemObject"); + cl_int result = originalFunction(mem); + if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive()) + { + GlobalTrace->logDeallocationEvent(mem); + } + + return result; +} +} diff --git a/runtime/contrib/heap_trace/src/free_stub.cc b/runtime/contrib/heap_trace/src/free_stub.cc new file mode 100644 index 000000000..31af63c8a --- /dev/null +++ b/runtime/contrib/heap_trace/src/free_stub.cc @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +void free(void *p) noexcept +{ + static auto originalFunction = findFunctionByName<void, void *>("free"); + originalFunction(p); + if (!Trace::Guard{}.isActive()) + { + GlobalTrace->logDeallocationEvent(p); + } +} +} diff --git a/runtime/contrib/heap_trace/src/function_resolver.h b/runtime/contrib/heap_trace/src/function_resolver.h new file mode 100644 index 000000000..9b6879539 --- /dev/null +++ b/runtime/contrib/heap_trace/src/function_resolver.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 FUNCTION_RESOLVER_H +#define FUNCTION_RESOLVER_H + +#include "symbol_searcher.h" + +template <typename ReturnType, typename... ArgTypes> +ReturnType (*findFunctionByName(const char *function_name))(ArgTypes...) +{ + auto found_symbol = findSymbol(function_name); + return reinterpret_cast<ReturnType (*)(ArgTypes...)>(found_symbol); +} + +#endif // ! FUNCTION_RESOLVER_H diff --git a/runtime/contrib/heap_trace/src/malloc_stub.cc b/runtime/contrib/heap_trace/src/malloc_stub.cc new file mode 100644 index 000000000..50124d164 --- /dev/null +++ b/runtime/contrib/heap_trace/src/malloc_stub.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +void *malloc(size_t sz) noexcept +{ + static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; }; + + static auto originalFunction = findFunctionByName<void *, size_t>("malloc"); + void *result = originalFunction(sz); + if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive()) + { + GlobalTrace->logAllocationEvent(result, sz); + } + + return result; +} +} diff --git a/runtime/contrib/heap_trace/src/realloc_stub.cc b/runtime/contrib/heap_trace/src/realloc_stub.cc new file mode 100644 index 000000000..ce4569b0e --- /dev/null +++ b/runtime/contrib/heap_trace/src/realloc_stub.cc @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +void *realloc(void *ptr, size_t sz) noexcept +{ + static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; }; + + static auto originalFunction = findFunctionByName<void *, void *, size_t>("realloc"); + void *result = originalFunction(ptr, sz); + if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive()) + { + GlobalTrace->logDeallocationEvent(ptr); + GlobalTrace->logAllocationEvent(result, sz); + } + + return result; +} +} diff --git a/runtime/contrib/heap_trace/src/symbol_searcher.cc b/runtime/contrib/heap_trace/src/symbol_searcher.cc new file mode 100644 index 000000000..cf83f2f7b --- /dev/null +++ b/runtime/contrib/heap_trace/src/symbol_searcher.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "symbol_searcher.h" + +#include <dlfcn.h> +#include <link.h> + +struct SymbolDescription +{ + const char *name; + void *address = nullptr; // address in memory where this symbol can be found + + SymbolDescription(const char *name) : name(name) {} +}; + +using InfoAboutLoadedLib = struct dl_phdr_info *; + +static void tryToFindSymbolInLinkedLibraries(SymbolDescription &symbol); +static void tryToFindSymbolInAllLoadedLibraries(SymbolDescription &symbol); +static int checkIfLibraryContainsSymbol(InfoAboutLoadedLib library_description, size_t /* size */, + void *data); +static bool isSymbolAddressNotInTheSameTranslationUnit(SymbolDescription *symbol); +void *findSymbol(const char *name) +{ + SymbolDescription symbol(name); + tryToFindSymbolInLinkedLibraries(symbol); + if (!symbol.address) + { + tryToFindSymbolInAllLoadedLibraries(symbol); + } + + return symbol.address; +} + +static void tryToFindSymbolInLinkedLibraries(SymbolDescription &symbol) +{ + symbol.address = dlsym(RTLD_NEXT, symbol.name); +} + +static void tryToFindSymbolInAllLoadedLibraries(SymbolDescription &symbol) +{ + dl_iterate_phdr(checkIfLibraryContainsSymbol, &symbol); +} + +static int checkIfLibraryContainsSymbol(InfoAboutLoadedLib library_description, size_t /* size */, + void *data) +{ + SymbolDescription *symbol = (SymbolDescription *)data; + + void *handle = dlopen(library_description->dlpi_name, RTLD_NOW); + symbol->address = dlsym(handle, symbol->name); + dlclose(handle); + if (symbol->address && isSymbolAddressNotInTheSameTranslationUnit(symbol)) + { + return 1; + } + return 0; +} + +static bool isSymbolAddressNotInTheSameTranslationUnit(SymbolDescription *symbol) +{ + void *handle = dlopen("", RTLD_NOW); + void *addressInTheSameTranslationUnit = dlsym(handle, symbol->name); + dlclose(handle); + + return addressInTheSameTranslationUnit == nullptr || + addressInTheSameTranslationUnit != symbol->address; +} diff --git a/runtime/contrib/heap_trace/src/symbol_searcher.h b/runtime/contrib/heap_trace/src/symbol_searcher.h new file mode 100644 index 000000000..f70a4e46f --- /dev/null +++ b/runtime/contrib/heap_trace/src/symbol_searcher.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 SYMBOL_SEARCHER_H +#define SYMBOL_SEARCHER_H + +void *findSymbol(const char *name); + +#endif // ! SYMBOL_SEARCHER_H diff --git a/runtime/contrib/heap_trace/src/trace.cc b/runtime/contrib/heap_trace/src/trace.cc new file mode 100644 index 000000000..82f2915cb --- /dev/null +++ b/runtime/contrib/heap_trace/src/trace.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" + +#include <memory> + +std::unique_ptr<Trace> GlobalTrace(new Trace); + +bool Trace::Guard::_is_trace_not_available = true; +thread_local bool Trace::Guard::_is_recursion_detected = false; + +Trace::Trace() +{ + if (!_out.is_open()) + { + _out.open(getLogFileNameFromEnvVariable("HEAP_TRACE_LOG")); + } + + Guard{}.markTraceAsReady(); +} + +const char *Trace::getLogFileNameFromEnvVariable(const char *env_variable_name) +{ + return getenv(env_variable_name); +} + +void Trace::logAllocationEvent(void *memory_ptr, size_t size_of_allocated_space_in_bytes) +{ + Guard{}.signalizeAboutPossibleRecursion(); + std::lock_guard<std::mutex> guard(_lock); + _total_allocated_bytes_on_cpu += size_of_allocated_space_in_bytes; + if (_peak_heap_usage_on_cpu < _total_allocated_bytes_on_cpu - _total_deallocated_bytes_on_cpu) + { + _peak_heap_usage_on_cpu = _total_allocated_bytes_on_cpu - _total_deallocated_bytes_on_cpu; + } + _memory_in_use_on_cpu[memory_ptr] = size_of_allocated_space_in_bytes; + Guard{}.signalizeThatDangerOfRecursionHAsPassed(); +} + +void Trace::logDeallocationEvent(void *memory_ptr) +{ + Guard{}.signalizeAboutPossibleRecursion(); + std::lock_guard<std::mutex> guard(_lock); + auto found_memory_space_description = _memory_in_use_on_cpu.find(memory_ptr); + if (found_memory_space_description != _memory_in_use_on_cpu.end()) + { + _total_deallocated_bytes_on_cpu += found_memory_space_description->second; + _memory_in_use_on_cpu.erase(found_memory_space_description); + } + Guard{}.signalizeThatDangerOfRecursionHAsPassed(); +} + +void Trace::logAllocationEvent(cl_mem memory_ptr, size_t size_of_allocated_space_in_bytes) +{ + Guard{}.signalizeAboutPossibleRecursion(); + std::lock_guard<std::mutex> guard(_lock); + _total_allocated_bytes_on_gpu += size_of_allocated_space_in_bytes; + if (_peak_heap_usage_on_gpu < _total_allocated_bytes_on_gpu - _total_deallocated_bytes_on_gpu) + { + _peak_heap_usage_on_gpu = _total_allocated_bytes_on_gpu - _total_deallocated_bytes_on_gpu; + } + _memory_in_use_on_gpu[memory_ptr] = size_of_allocated_space_in_bytes; + Guard{}.signalizeThatDangerOfRecursionHAsPassed(); +} + +void Trace::logDeallocationEvent(cl_mem memory_ptr) +{ + Guard{}.signalizeAboutPossibleRecursion(); + std::lock_guard<std::mutex> guard(_lock); + auto found_memory_space_description = _memory_in_use_on_gpu.find(memory_ptr); + if (found_memory_space_description != _memory_in_use_on_gpu.end()) + { + _total_deallocated_bytes_on_gpu += found_memory_space_description->second; + _memory_in_use_on_gpu.erase(found_memory_space_description); + } + Guard{}.signalizeThatDangerOfRecursionHAsPassed(); +} + +Trace::~Trace() +{ + Guard{}.markTraceAsNotReady(); + + _out << "On CPU - Peak heap usage: " << _peak_heap_usage_on_cpu + << " B, Total allocated: " << _total_allocated_bytes_on_cpu + << " B, Total deallocated: " << _total_deallocated_bytes_on_cpu << " B\n"; + _out << "On GPU - Peak mem usage: " << _peak_heap_usage_on_gpu + << " B, Total allocated: " << _total_allocated_bytes_on_gpu + << " B, Total deallocated: " << _total_deallocated_bytes_on_gpu << " B\n"; +} diff --git a/runtime/contrib/heap_trace/src/trace.h b/runtime/contrib/heap_trace/src/trace.h new file mode 100644 index 000000000..f03a65a58 --- /dev/null +++ b/runtime/contrib/heap_trace/src/trace.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 TRACE_H_ +#define TRACE_H_ + +#include <CL/cl.h> + +#include <unordered_map> +#include <fstream> +#include <mutex> + +class Trace +{ +public: + class Guard + { + friend class Trace; + + public: + bool isActive() { return _is_trace_not_available || _is_recursion_detected; } + + private: + void markTraceAsReady() { _is_trace_not_available = false; } + void markTraceAsNotReady() { _is_trace_not_available = true; } + void signalizeAboutPossibleRecursion() { _is_recursion_detected = true; } + void signalizeThatDangerOfRecursionHAsPassed() { _is_recursion_detected = false; } + + private: + static bool _is_trace_not_available; + static thread_local bool _is_recursion_detected; + }; + +public: + Trace(); + Trace(const Trace &) = delete; + const Trace &operator=(const Trace &) = delete; + + void logAllocationEvent(void *memory_ptr, size_t size_of_allocated_space_in_bytes); + void logAllocationEvent(cl_mem memory_ptr, size_t size_of_allocated_space_in_bytes); + void logDeallocationEvent(void *memory_ptr); + void logDeallocationEvent(cl_mem memory_ptr); + + ~Trace(); + +private: + const char *getLogFileNameFromEnvVariable(const char *env_variable_name); + +private: + std::mutex _lock; + std::ofstream _out; + size_t _total_allocated_bytes_on_cpu = 0; + size_t _total_deallocated_bytes_on_cpu = 0; + size_t _peak_heap_usage_on_cpu = 0; + size_t _total_allocated_bytes_on_gpu = 0; + size_t _total_deallocated_bytes_on_gpu = 0; + size_t _peak_heap_usage_on_gpu = 0; + std::unordered_map<void *, size_t> _memory_in_use_on_cpu; + std::unordered_map<cl_mem, size_t> _memory_in_use_on_gpu; +}; + +#endif // !TRACE_H diff --git a/runtime/contrib/heap_trace/src/valloc_stub.cc b/runtime/contrib/heap_trace/src/valloc_stub.cc new file mode 100644 index 000000000..24e91bd11 --- /dev/null +++ b/runtime/contrib/heap_trace/src/valloc_stub.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved + * + * Licensed under 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 "trace.h" +#include "function_resolver.h" + +#include <memory> + +extern std::unique_ptr<Trace> GlobalTrace; + +extern "C" { + +void *valloc(size_t sz) noexcept +{ + static auto isOriginalFunctionCallSuccessful = [](void *result) -> bool { return result; }; + + static auto originalFunction = findFunctionByName<void *, size_t>("valloc"); + void *result = originalFunction(sz); + if (isOriginalFunctionCallSuccessful(result) && !Trace::Guard{}.isActive()) + { + GlobalTrace->logAllocationEvent(result, sz); + } + + return result; +} +} |