From e85548dcba4a996f00261b73efef9580601a8676 Mon Sep 17 00:00:00 2001 From: Alexander A Raud Date: Fri, 5 Feb 2016 17:33:38 +0300 Subject: [PATCH 01/54] Java impl cpp --- java/com_intel_sea_IntelSEAPI.cpp | 98 +++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 java/com_intel_sea_IntelSEAPI.cpp diff --git a/java/com_intel_sea_IntelSEAPI.cpp b/java/com_intel_sea_IntelSEAPI.cpp new file mode 100644 index 0000000..98df457 --- /dev/null +++ b/java/com_intel_sea_IntelSEAPI.cpp @@ -0,0 +1,98 @@ +#include "java/com_intel_sea_IntelSEAPI.h" +#include "ittnotify.h" + +extern "C" { + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createDomain(JNIEnv* pEnv, jclass, jstring name) + { + const char * nativeString = pEnv->GetStringUTFChars(name, nullptr); + if (!nativeString) return 0; + __itt_domain* pDomain = __itt_domain_create(nativeString); + pEnv->ReleaseStringUTFChars(name, nativeString); + return (jlong)pDomain; + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createString(JNIEnv * pEnv, jclass, jstring name) + { + const char * nativeString = pEnv->GetStringUTFChars(name, nullptr); + if (!nativeString) return 0; + __itt_string_handle* pString = __itt_string_handle_create(nativeString); + pEnv->ReleaseStringUTFChars(name, nativeString); + return (jlong)pString; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_beginTask(JNIEnv * pEnv, jclass, jlong domain, jlong name, jlong id, jlong parent, jlong timestamp) + { + __itt_task_begin_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, + timestamp, + id ? __itt_id_make((void*)domain, id) : __itt_null, + parent ? __itt_id_make((void*)domain, parent) : __itt_null, + reinterpret_cast<__itt_string_handle*>(name) + ); + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_endTask(JNIEnv *, jclass, jlong domain, jlong timestamp) + { + __itt_task_end_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, + timestamp + ); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_counterCreate(JNIEnv *, jclass, jlong domain, jlong name) + { + __itt_counter conuter = __itt_counter_create_typed( + reinterpret_cast<__itt_string_handle*>(name)->strA, + reinterpret_cast<__itt_domain*>(domain)->nameA, + __itt_metadata_double + ); + return (jlong)conuter; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_setCounter(JNIEnv *, jclass, jlong counter, jdouble value, jlong timestamp) + { + __itt_counter_set_value_ex(reinterpret_cast<__itt_counter>(counter), nullptr, timestamp, &value); + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_marker(JNIEnv *, jclass, jlong domain, jlong id, jlong name, jlong scope, jlong timestamp) + { + __itt_marker_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, //zero clock domain means that given time is already a correct timestamp + timestamp, + id ? __itt_id_make((void*)domain, id) : __itt_null, + reinterpret_cast<__itt_string_handle*>(name), + (__itt_scope)scope + ); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createTrack(JNIEnv * pEnv, jclass, jstring group, jstring track) + { + const char * szGroup = group ? pEnv->GetStringUTFChars(group, nullptr) : nullptr; + const char * szTrack = pEnv->GetStringUTFChars(track, nullptr); + + __itt_track* pTrack = __itt_track_create( + __itt_track_group_create(((group) ? __itt_string_handle_create(szGroup) : nullptr), __itt_track_group_type_normal), + __itt_string_handle_create(szTrack), + __itt_track_type_normal + ); + + pEnv->ReleaseStringUTFChars(track, szTrack); + if (group) + pEnv->ReleaseStringUTFChars(group, szGroup); + + return (jlong)pTrack; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_setTrack(JNIEnv *, jclass, jlong track) + { + __itt_set_track(reinterpret_cast<__itt_track*>(track)); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_getTimestamp(JNIEnv *, jclass) + { + return (jlong)__itt_get_timestamp(); + } +} From 6f9e3c1ca86e9ffb5d61043bfba70eba1b36e330 Mon Sep 17 00:00:00 2001 From: Alexander A Raud Date: Sat, 6 Feb 2016 22:21:35 +0300 Subject: [PATCH 02/54] memory attribution to functions better stack handling --- runtool/sea_runtool.py | 64 ++++++++++++++++++---- sea_itt_lib/IttNotifyStdSrc.cpp | 87 ++---------------------------- sea_itt_lib/IttNotifyStdSrc.h | 9 +++- sea_itt_lib/Recorder.cpp | 7 +-- sea_itt_lib/Utils.cpp | 94 +++++++++++++++++++++++++++++++-- sea_itt_lib/sea_itt_lib.cpp | 11 ++-- 6 files changed, 165 insertions(+), 107 deletions(-) diff --git a/runtool/sea_runtool.py b/runtool/sea_runtool.py index 2d9e4cd..ee63992 100644 --- a/runtool/sea_runtool.py +++ b/runtool/sea_runtool.py @@ -348,7 +348,7 @@ def sea_reader(folder): #reads the structure of .sea format folder into dictiona elif filename.endswith(".pid"): #named groups (pseudo pids) makes record: group is the handle and content is the value tree["groups"][filename.replace(".pid", "")] = file.readline() elif filename.endswith(".mdl"): #registered modules - for symbol resolving - tree["modules"][int(filename.replace(".mdl", ""))] = file.readline() + tree["modules"][int(filename.replace(".mdl", ""))] = file.readline().split() elif filename == "process.dct": #process info tree["process"] = eval(file.read()) for domain in toplevel[1]:#data from every domain gets recorded into separate folder which is named after the domain name @@ -638,8 +638,9 @@ def get_module_by_ptr(tree, ptr): if key > ptr: break; item = key - if item < ptr: - return (item, tree['modules'][item]) + module = tree['modules'][item] + if item < ptr < item + int(module[1]): + return (item, module[0]) else: return (None, None) @@ -680,8 +681,11 @@ def resolve_pointer(args, tree, ptr, call, cache = {}): call['str'] = lines[1] (call['__file__'], call['__line__']) = lines[0].rstrip(")").rsplit("(", 1) elif sys.platform == 'darwin': - if '+' in lines[0]: - call['str'] = lines[0].split(" (in ")[0] + if '(in' in lines[0]: + parts = lines[0].split(" (in ") + call['str'] = parts[0] + (call['__file__'], call['__line__']) = parts[1].split(") (")[1].split(':') + call['__line__'] = call['__line__'].strip(')') else: return False else: @@ -778,6 +782,7 @@ def __init__(self, tree): self.events = [] self.event_map = {} self.prev_sample = 0 + self.memory = {} def global_metadata(self, data): pass @@ -830,14 +835,28 @@ def get_task(id): return None def find_task(id): - for _, thread_stacks in domain['tasks'].iteritems(): #look in all threads - if thread_stacks['byid'].has_key(id) and len(thread_stacks['byid'][id]): + for thread_stacks in domain['tasks'].itervalues(): #look in all threads + if thread_stacks['byid'].has_key(id) and thread_stacks['byid'][id]: return thread_stacks['byid'][id][-1] else: for item in thread_stacks['stack']: if item.has_key('id') and item['id'] == id: return item + def current_task(tid): + candidates = [] + for domain in self.domains.itervalues(): + if not domain['tasks'].has_key(tid): + continue + thread = domain['tasks'][tid] + for byid in thread['byid'].itervalues(): + if byid: + candidates.append(byid[-1]) + if thread['stack']: + candidates.append(thread['stack'][-1]) + candidates.sort(key=lambda item: item['time']) + return candidates[-1] if candidates else None + def get_last_index(tasks, type): if not len(tasks): return None @@ -931,6 +950,17 @@ def get_last_index(tasks, type): counter['begin'] = min(counter['begin'], data['time']) counter['end'] = max(counter['end'], data['time']) else: + if data['domain'] == 'Memory': + counter_name = data['str'] + prev_value = 0. + if self.memory.has_key(counter_name): + prev_value = self.memory[counter_name] + delta = data['delta'] - prev_value #data['delta'] has current value of the counter + self.memory[counter_name] = data['delta'] + current = current_task(data['tid']) + if current: + values = current.setdefault('memory',{}).setdefault(counter_name, []) + values.append(delta) self.complete_task(fn, data, data) elif fn == "relation": self.relation( @@ -1126,8 +1156,8 @@ def complete_task(self, type, begin, end): if not res: return - if type in ['task', 'counter'] and begin.has_key('data'): #FIXME: move closer to the place where stack is demanded - self.handle_stack(begin, resolve_stack(self.args, self.tree, begin['data']), type) + if type in ['task', 'counter'] and begin.has_key('data') and begin.has_key('str'): #FIXME: move closer to the place where stack is demanded + self.handle_stack(begin, resolve_stack(self.args, self.tree, begin['data']), begin['str']) if self.args.debug: res = "".join(res) try: @@ -1143,6 +1173,8 @@ def complete_task(self, type, begin, end): self.start_new_trace() def handle_stack(self, task, stack, name='stack'): + if not stack: + return parent = None for frame in reversed(stack): #going from parents to childs if parent == None: @@ -1237,6 +1269,17 @@ def format_task(self, phase, type, begin, end): args["__line__"] = begin["__line__"] if 'counter' == type: args[name] = begin['delta'] + if begin.has_key('memory'): + total = 0 + breakdown = {} + for name, values in begin['memory'].iteritems(): + size = int(name.split('<')[1].split('>')[0]) + all = sum(values) + total += size * all + if all: + breakdown[size] = all + breakdown['TOTAL'] = total + args['CRT:Memory'] = breakdown if args: res.append(', "args":') res.append(self.format_value(args)) @@ -1523,7 +1566,8 @@ def make_id(self, domain, name): return re.sub("[^a-z0-9]", "_", res.lower()) def relation(self, data, head, tail): - self.add_relation({'label': data['str'], 'from': self.make_id(head['domain'], head['str']), 'to': self.make_id(tail['domain'], tail['str']), 'color': 'red'}) + if head and tail: + self.add_relation({'label': data['str'], 'from': self.make_id(head['domain'], head['str']), 'to': self.make_id(tail['domain'], tail['str']), 'color': 'red'}) def add_relation(self, relation): key = frozenset(relation.iteritems()) diff --git a/sea_itt_lib/IttNotifyStdSrc.cpp b/sea_itt_lib/IttNotifyStdSrc.cpp index 307531c..ce09025 100644 --- a/sea_itt_lib/IttNotifyStdSrc.cpp +++ b/sea_itt_lib/IttNotifyStdSrc.cpp @@ -30,78 +30,12 @@ #ifdef _WIN32 #include #include -#else - #ifndef __ANDROID__ - #include - #endif - #include - #include #endif - -#ifdef __APPLE__ - #include -#endif - -namespace sea { //TODO: consider moving to Utils.cpp - +namespace sea { IHandler* g_handlers[MAX_HANDLERS] = {}; //10 is more than enough for now - -#ifdef _WIN32 -const char* GetProcessName(bool bFullPath) -{ - assert(bFullPath); - static char process_name[1024] = {}; - if (!process_name[0]) - GetModuleFileNameA(NULL, process_name, sizeof(process_name) - 1); - return process_name; -} - -TMdlInfo Fn2Mdl(void* fn) -{ - HMODULE hModule = NULL; - GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)fn, &hModule); - char filename[1024] = {}; - GetModuleFileNameA(hModule, filename, sizeof(filename) - 1); - return TMdlInfo(hModule, filename); -} - -#else - -sea::TMdlInfo Fn2Mdl(void* fn) -{ - Dl_info dl_info = {}; - dladdr(fn, &dl_info); - if (dl_info.dli_fname[0] == '/') //path is absolute - return TMdlInfo(dl_info.dli_fbase, dl_info.dli_fname); - else - { - const char * absolute = realpath(dl_info.dli_fname, nullptr); - TMdlInfo mdlInfo(dl_info.dli_fbase, absolute); - free((void*) absolute); - return mdlInfo; - } } -const char* GetProcessName(bool bFullPath) -{ - static char process_name[1024] = {}; -#ifdef __APPLE__ - uint32_t size = 1023; - _NSGetExecutablePath(process_name, &size); -#else - if (!process_name[0]) - process_name[readlink("/proc/self/exe", process_name, sizeof(process_name)/sizeof(process_name[0]) - 1 )] = 0; -#endif //__APPLE__ - if (bFullPath) return process_name; - return strrchr(process_name, '/') + 1; -} - -#endif - -} //namespace sea - - //FIXME: in general add much more comments std::map g_stats; //can't be static function variable due to lifetime limits @@ -588,6 +522,7 @@ void counter_set_value(__itt_counter id, void *value_ptr) void UNICODE_AGNOSTIC(sync_create)(void *addr, const char *objtype, const char *objname, int attribute) { + return; //XXX ITT_FUNCTION_STAT(); std::string name((attribute == __itt_attr_mutex) ? "mutex:" : "barrier:"); @@ -610,6 +545,7 @@ void sync_createW(void *addr, const wchar_t *objtype, const wchar_t *objname, in void sync_destroy(void *addr) { + return; //XXX ITT_FUNCTION_STAT(); __itt_id id = __itt_id_make(addr, 0); @@ -619,6 +555,7 @@ void sync_destroy(void *addr) inline void SyncState(void * addr, const char * state) { + return; //XXX __itt_id id = __itt_id_make(addr, 0); CTraceEventFormat::SRegularFields rf = GetRegularFields(); @@ -1254,7 +1191,6 @@ class CMemoryTracker typedef std::pair<__itt_string_handle*, size_t/*count*/> TBlockData; std::map m_counter_map; bool m_bInitialized = false; - size_t m_common_size = 0; public: CMemoryTracker() : m_bInitialized(true) @@ -1277,23 +1213,9 @@ class CMemoryTracker { ++it->second.second; } - m_common_size += size; block = it->second; } Counter(pHeapFunction->pDomain, block.first, double(block.second)); -/*XXX - Counter(pHeapFunction->pDomain, pHeapFunction->pName, double(m_common_size)); - if (STaskDescriptor* pTask = GetThreadRecord()->pTask) - { - for (size_t i = 0; (i < MAX_HANDLERS) && g_handlers[i]; ++i) - { - //TODO: this show blocks allocated by this task with their number on this moment - //but user needs to know how many is allocated by this task, not common value on this moment - std::string data = std::to_string(it->second.second); - g_handlers[i]->AddArg(*pTask, it->second.first, data.c_str(), data.size()); - } - } -*/ } void Free(SHeapFunction* pHeapFunction, const void* addr) @@ -1311,7 +1233,6 @@ class CMemoryTracker { --it->second.second; } - m_common_size -= size; Counter(pHeapFunction->pDomain, it->second.first, double(it->second.second)); } diff --git a/sea_itt_lib/IttNotifyStdSrc.h b/sea_itt_lib/IttNotifyStdSrc.h index 9bfaf73..f7c2a6f 100644 --- a/sea_itt_lib/IttNotifyStdSrc.h +++ b/sea_itt_lib/IttNotifyStdSrc.h @@ -72,8 +72,13 @@ namespace sea { void SetFolder(const std::string& path); void SetRing(uint64_t nanoseconds); const char* GetProcessName(bool bFullPath); - typedef std::pair TMdlInfo; - TMdlInfo Fn2Mdl(void* fn); + struct SModuleInfo + { + void* base; + size_t size; + std::string path; + }; + SModuleInfo Fn2Mdl(void* fn); std::string GetDir(std::string path, const std::string& append = ""); } diff --git a/sea_itt_lib/Recorder.cpp b/sea_itt_lib/Recorder.cpp index f8328b2..adeda45 100644 --- a/sea_itt_lib/Recorder.cpp +++ b/sea_itt_lib/Recorder.cpp @@ -516,12 +516,13 @@ bool ReportModule(void* fn) if (g_savepath.empty()) return true; - TMdlInfo module_info = Fn2Mdl(fn); + SModuleInfo module_info = Fn2Mdl(fn); - std::string path = GetDir(g_savepath) + std::to_string((uint64_t)module_info.first) + ".mdl"; + std::string path = GetDir(g_savepath) + std::to_string((uint64_t)module_info.base) + ".mdl"; int fd = open(path.c_str(), O_WRONLY|O_CREAT|O_EXCL, FilePermissions); if (-1 == fd) return true; //file already exists - int res = write(fd, module_info.second.c_str(), (unsigned int)module_info.second.size()); + std::string text = module_info.path + " " + std::to_string(module_info.size); + int res = write(fd, text.c_str(), (unsigned int)text.size()); close(fd); return res != -1; } diff --git a/sea_itt_lib/Utils.cpp b/sea_itt_lib/Utils.cpp index 7452524..a41cfee 100644 --- a/sea_itt_lib/Utils.cpp +++ b/sea_itt_lib/Utils.cpp @@ -17,6 +17,24 @@ **********************************************************************************************************************************************************************************************************************************************************************************************/ #include "Utils.h" +#include "IttNotifyStdSrc.h" +#include + +#ifdef _WIN32 + #include +#else + #include + #include + + #ifndef __ANDROID__ + #include + #endif + +#endif + +#ifdef __APPLE__ + #include +#endif #ifdef __ANDROID__ @@ -54,10 +72,6 @@ size_t GetStack(TStack& stack) #else -#ifndef _WIN32 - #include -#endif - size_t GetStack(TStack& stack) { #ifdef _WIN32 @@ -69,3 +83,75 @@ size_t GetStack(TStack& stack) #endif } #endif + +namespace sea { + +#ifdef _WIN32 +const char* GetProcessName(bool bFullPath) +{ + assert(bFullPath); + static char process_name[1024] = {}; + if (!process_name[0]) + GetModuleFileNameA(NULL, process_name, sizeof(process_name) - 1); + return process_name; +} + +SModuleInfo Fn2Mdl(void* fn) +{ + HMODULE hModule = NULL; + GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)fn, &hModule); + char filename[1024] = {}; + GetModuleFileNameA(hModule, filename, sizeof(filename) - 1); + MODULEINFO mi = {}; + GetModuleInformation(GetCurrentProcess(), hModule, &mi, sizeof(MODULEINFO)); + return SModuleInfo{hModule, mi.SizeOfImage, filename}; +} + +#else + +#include + +size_t GetFileSize(const char *path) { + struct stat st = {}; + + if (0 == stat(path, &st)) + return st.st_size; + + return -1; +} + +sea::SModuleInfo Fn2Mdl(void* fn) +{ + //FIXME: Linux: dl_iterate_phdr(), OSX: http://stackoverflow.com/questions/28846503/getting-sizeofimage-and-entrypoint-of-dylib-module + Dl_info dl_info = {}; + dladdr(fn, &dl_info); + if (dl_info.dli_fname[0] == '/') //path is absolute + return SModuleInfo{dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), dl_info.dli_fname}; + else + { + const char * absolute = realpath(dl_info.dli_fname, nullptr); + SModuleInfo mdlInfo{dl_info.dli_fbase, GetFileSize(dl_info.dli_fname), absolute}; + free((void*) absolute); + return mdlInfo; + } +} + +const char* GetProcessName(bool bFullPath) +{ + static char process_name[1024] = {}; +#ifdef __APPLE__ + uint32_t size = 1023; + _NSGetExecutablePath(process_name, &size); +#else + if (!process_name[0]) + process_name[readlink("/proc/self/exe", process_name, sizeof(process_name)/sizeof(process_name[0]) - 1 )] = 0; +#endif //__APPLE__ + if (bFullPath) return process_name; + return strrchr(process_name, '/') + 1; +} + +#endif + +} //namespace sea + + diff --git a/sea_itt_lib/sea_itt_lib.cpp b/sea_itt_lib/sea_itt_lib.cpp index 69e9111..f72f84e 100644 --- a/sea_itt_lib/sea_itt_lib.cpp +++ b/sea_itt_lib/sea_itt_lib.cpp @@ -19,6 +19,7 @@ #include "IttNotifyStdSrc.h" +#include "Utils.h" #include #include #include @@ -45,13 +46,13 @@ int GlobalInit() { static const char var_name[] = INTEL_LIBITTNOTIFY BIT_SUFFIX; - sea::TMdlInfo mdlinfo = sea::Fn2Mdl((void*)GlobalInit); + sea::SModuleInfo mdlinfo = sea::Fn2Mdl((void*)GlobalInit); - VerbosePrint("IntelSEAPI: %s=%s | Loaded from: %s\n", var_name, get_environ_value(var_name).c_str(), mdlinfo.second.c_str()); + VerbosePrint("IntelSEAPI: %s=%s | Loaded from: %s\n", var_name, get_environ_value(var_name).c_str(), mdlinfo.path.c_str()); std::string value = var_name; value += "="; - value += mdlinfo.second; + value += mdlinfo.path; setenv(_strdup(value.c_str())); return 1; @@ -113,8 +114,8 @@ extern "C" { SEA_EXPORT void ITTAPI __itt_api_init(__itt_global* pGlob, __itt_group_id id) { const char* procname = sea::GetProcessName(true); - sea::TMdlInfo mdlinfo = sea::Fn2Mdl(pGlob); - VerbosePrint("IntelSEAPI init is called from process '%s' at module '%s'\n", procname, mdlinfo.second.c_str()); + sea::SModuleInfo mdlinfo = sea::Fn2Mdl(pGlob); + VerbosePrint("IntelSEAPI init is called from process '%s' at module '%s'\n", procname, mdlinfo.path.c_str()); GetITTGlobal(pGlob); sea::FillApiList(pGlob->api_list_ptr); for (___itt_domain* pDomain = pGlob->domain_list; pDomain; pDomain = pDomain->next) From cba4c26d527efb7258276a0082a842f0f5826e77 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 18 Feb 2016 22:27:10 +0300 Subject: [PATCH 03/54] ignores --- .gitignore | 1 + java/com_intel_sea_IntelSEAPI.cpp | 98 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 .gitignore create mode 100644 java/com_intel_sea_IntelSEAPI.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e331af1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build_win/ diff --git a/java/com_intel_sea_IntelSEAPI.cpp b/java/com_intel_sea_IntelSEAPI.cpp new file mode 100644 index 0000000..98df457 --- /dev/null +++ b/java/com_intel_sea_IntelSEAPI.cpp @@ -0,0 +1,98 @@ +#include "java/com_intel_sea_IntelSEAPI.h" +#include "ittnotify.h" + +extern "C" { + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createDomain(JNIEnv* pEnv, jclass, jstring name) + { + const char * nativeString = pEnv->GetStringUTFChars(name, nullptr); + if (!nativeString) return 0; + __itt_domain* pDomain = __itt_domain_create(nativeString); + pEnv->ReleaseStringUTFChars(name, nativeString); + return (jlong)pDomain; + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createString(JNIEnv * pEnv, jclass, jstring name) + { + const char * nativeString = pEnv->GetStringUTFChars(name, nullptr); + if (!nativeString) return 0; + __itt_string_handle* pString = __itt_string_handle_create(nativeString); + pEnv->ReleaseStringUTFChars(name, nativeString); + return (jlong)pString; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_beginTask(JNIEnv * pEnv, jclass, jlong domain, jlong name, jlong id, jlong parent, jlong timestamp) + { + __itt_task_begin_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, + timestamp, + id ? __itt_id_make((void*)domain, id) : __itt_null, + parent ? __itt_id_make((void*)domain, parent) : __itt_null, + reinterpret_cast<__itt_string_handle*>(name) + ); + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_endTask(JNIEnv *, jclass, jlong domain, jlong timestamp) + { + __itt_task_end_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, + timestamp + ); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_counterCreate(JNIEnv *, jclass, jlong domain, jlong name) + { + __itt_counter conuter = __itt_counter_create_typed( + reinterpret_cast<__itt_string_handle*>(name)->strA, + reinterpret_cast<__itt_domain*>(domain)->nameA, + __itt_metadata_double + ); + return (jlong)conuter; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_setCounter(JNIEnv *, jclass, jlong counter, jdouble value, jlong timestamp) + { + __itt_counter_set_value_ex(reinterpret_cast<__itt_counter>(counter), nullptr, timestamp, &value); + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_marker(JNIEnv *, jclass, jlong domain, jlong id, jlong name, jlong scope, jlong timestamp) + { + __itt_marker_ex( + reinterpret_cast<__itt_domain*>(domain), + nullptr, //zero clock domain means that given time is already a correct timestamp + timestamp, + id ? __itt_id_make((void*)domain, id) : __itt_null, + reinterpret_cast<__itt_string_handle*>(name), + (__itt_scope)scope + ); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_createTrack(JNIEnv * pEnv, jclass, jstring group, jstring track) + { + const char * szGroup = group ? pEnv->GetStringUTFChars(group, nullptr) : nullptr; + const char * szTrack = pEnv->GetStringUTFChars(track, nullptr); + + __itt_track* pTrack = __itt_track_create( + __itt_track_group_create(((group) ? __itt_string_handle_create(szGroup) : nullptr), __itt_track_group_type_normal), + __itt_string_handle_create(szTrack), + __itt_track_type_normal + ); + + pEnv->ReleaseStringUTFChars(track, szTrack); + if (group) + pEnv->ReleaseStringUTFChars(group, szGroup); + + return (jlong)pTrack; + } + + JNIEXPORT void JNICALL Java_com_intel_sea_IntelSEAPI_setTrack(JNIEnv *, jclass, jlong track) + { + __itt_set_track(reinterpret_cast<__itt_track*>(track)); + } + + JNIEXPORT jlong JNICALL Java_com_intel_sea_IntelSEAPI_getTimestamp(JNIEnv *, jclass) + { + return (jlong)__itt_get_timestamp(); + } +} From eefa8f6850165f744e44d8df0ed0408baf5e2686 Mon Sep 17 00:00:00 2001 From: Alexander A Raud Date: Tue, 23 Feb 2016 15:40:04 +0300 Subject: [PATCH 04/54] explicit split to importers and exporters small bugfix --- buildall.py | 7 +- java/IntelSEAPI.java | 18 + runtool/exporters/BestTraceFormat.py | 52 + runtool/exporters/ChromeTracing.py | 368 +++++ runtool/exporters/DGML.py | 74 + runtool/exporters/GraphViz.py | 82 ++ runtool/exporters/QtCreatorProfiler.py | 164 +++ runtool/importers/etw.py | 644 +++++++++ runtool/sea.py | 17 + runtool/sea_runtool.py | 1748 ++++-------------------- sea_itt_lib/TraceEventFormat.h | 2 +- test_linux.sh | 0 test_osx.sh | 2 +- 13 files changed, 1694 insertions(+), 1484 deletions(-) create mode 100644 runtool/exporters/BestTraceFormat.py create mode 100644 runtool/exporters/ChromeTracing.py create mode 100644 runtool/exporters/DGML.py create mode 100644 runtool/exporters/GraphViz.py create mode 100644 runtool/exporters/QtCreatorProfiler.py create mode 100644 runtool/importers/etw.py mode change 100644 => 100755 test_linux.sh diff --git a/buildall.py b/buildall.py index 2fbc729..5b07311 100644 --- a/buildall.py +++ b/buildall.py @@ -85,7 +85,8 @@ def GetJDKPath(): if err or not path: return None if sys.platform == 'darwin': - return "/System/Library/Frameworks/JavaVM.framework/Headers" + path = "/System/Library/Frameworks/JavaVM.framework/Headers" + return (path if os.path.exists(path) else None) else: matches = [] for root, dirnames, filenames in os.walk('/usr/lib/jvm'): @@ -107,11 +108,13 @@ def main(): yocto = get_yocto() if not yocto: target_bits = ['64'] - if sys.platform != 'darwin': #on MAC OSX we produce FAT library including both 32 and 64 bits + if (sys.platform != 'darwin') or args.android: #on MAC OSX we produce FAT library including both 32 and 64 bits target_bits.append('32') else: target_bits = [yocto['bits']] + print "target_bits", target_bits + jdk_path = GetJDKPath() print "Found JDK:", jdk_path diff --git a/java/IntelSEAPI.java b/java/IntelSEAPI.java index 855e3e8..0d935ef 100644 --- a/java/IntelSEAPI.java +++ b/java/IntelSEAPI.java @@ -1,3 +1,21 @@ +/********************************************************************************************************************************************************************************************************************************************************************************************* +# Intel® Single Event API +# +# This file is provided under a dual BSD 3-Clause license. +# Copyright (c) 2015, Intel Corporation +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +# Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +# Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +**********************************************************************************************************************************************************************************************************************************************************************************************/ + package com.intel.sea; import java.util.*; import java.io.File; diff --git a/runtool/exporters/BestTraceFormat.py b/runtool/exporters/BestTraceFormat.py new file mode 100644 index 0000000..a2eefc3 --- /dev/null +++ b/runtool/exporters/BestTraceFormat.py @@ -0,0 +1,52 @@ +from sea_runtool import TaskCombiner + +################################### +# TODO: add OS events (sched/vsync) +class BestTraceFormat(TaskCombiner): + """Writer for Best Trace Format. + + Specs for BTF v2.1.3: https://wiki.eclipse.org/images/e/e6/TA_BTF_Specification_2.1.3_Eclipse_Auto_IWG.pdf + """ + + def __init__(self, args, tree): + """Open the .btf file and write its header.""" + TaskCombiner.__init__(self, tree) + self.args = args + self.file = open(self.get_targets()[-1], "w+b") + self.file.write('#version 2.1.3\n') + self.file.write('#creator GDP-SEA\n') + self.file.write('#creationDate 2014-02-19T11:39:20Z\n') + self.file.write('#timeScale ns\n') + + def get_targets(self): + return [self.args.output + ".btf"] + + def complete_task(self, type, b, e): + """ + type -- task type : {"task", "frame", "counter"} + b -- { 'thread_name': '0x6296', 'domain': 'gles.trace.ergs', 'str': 'glPopMatrix', 'time': 1443097648250368731, 'tid': 25238, 'pid': 25238} + e -- { 'tid': 25238, 'thread_name': '0x6296', 'domain': 'gles.trace.ergs', 'pid': 25238, 'time': 1443097648250548143} + """ + #