aot_perf_map.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "aot_perf_map.h"
  6. #include "bh_log.h"
  7. #include "bh_platform.h"
  8. #if WASM_ENABLE_LINUX_PERF != 0
  9. struct func_info {
  10. uint32 idx;
  11. void *ptr;
  12. };
  13. static uint32
  14. get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
  15. uint32 idx)
  16. {
  17. uint32 func_sz;
  18. if (idx == module->func_count - 1)
  19. func_sz = (uintptr_t)module->code + module->code_size
  20. - (uintptr_t)(sorted_func_ptrs[idx].ptr);
  21. else
  22. func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
  23. - (uintptr_t)(sorted_func_ptrs[idx].ptr);
  24. return func_sz;
  25. }
  26. static int
  27. compare_func_ptrs(const void *f1, const void *f2)
  28. {
  29. return (intptr_t)((struct func_info *)f1)->ptr
  30. - (intptr_t)((struct func_info *)f2)->ptr;
  31. }
  32. static struct func_info *
  33. sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
  34. {
  35. uint64 content_len;
  36. struct func_info *sorted_func_ptrs;
  37. unsigned i;
  38. content_len = (uint64)sizeof(struct func_info) * module->func_count;
  39. sorted_func_ptrs = wasm_runtime_malloc(content_len);
  40. if (!sorted_func_ptrs) {
  41. snprintf(error_buf, error_buf_size,
  42. "allocate memory failed when creating perf map");
  43. return NULL;
  44. }
  45. for (i = 0; i < module->func_count; i++) {
  46. sorted_func_ptrs[i].idx = i;
  47. sorted_func_ptrs[i].ptr = module->func_ptrs[i];
  48. }
  49. qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
  50. compare_func_ptrs);
  51. return sorted_func_ptrs;
  52. }
  53. bool
  54. aot_create_perf_map(const AOTModule *module, char *error_buf,
  55. uint32 error_buf_size)
  56. {
  57. struct func_info *sorted_func_ptrs = NULL;
  58. char perf_map_path[64] = { 0 };
  59. char perf_map_info[128] = { 0 };
  60. FILE *perf_map = NULL;
  61. uint32 i;
  62. pid_t pid = getpid();
  63. bool ret = false;
  64. sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
  65. if (!sorted_func_ptrs)
  66. goto quit;
  67. snprintf(perf_map_path, sizeof(perf_map_path) - 1, "/tmp/perf-%d.map", pid);
  68. perf_map = fopen(perf_map_path, "a");
  69. if (!perf_map) {
  70. LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
  71. strerror(errno));
  72. goto quit;
  73. }
  74. const char *module_name = aot_get_module_name((AOTModule *)module);
  75. for (i = 0; i < module->func_count; i++) {
  76. memset(perf_map_info, 0, 128);
  77. if (strlen(module_name) > 0)
  78. snprintf(perf_map_info, 128, "%lx %x [%s]#aot_func#%u\n",
  79. (uintptr_t)sorted_func_ptrs[i].ptr,
  80. get_func_size(module, sorted_func_ptrs, i), module_name,
  81. sorted_func_ptrs[i].idx);
  82. else
  83. snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
  84. (uintptr_t)sorted_func_ptrs[i].ptr,
  85. get_func_size(module, sorted_func_ptrs, i),
  86. sorted_func_ptrs[i].idx);
  87. /* fwrite() is thread safe */
  88. fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
  89. }
  90. LOG_VERBOSE("write map information from %s into /tmp/perf-%d.map",
  91. module_name, pid);
  92. ret = true;
  93. quit:
  94. if (sorted_func_ptrs)
  95. wasm_runtime_free(sorted_func_ptrs);
  96. if (perf_map)
  97. fclose(perf_map);
  98. return ret;
  99. }
  100. #endif /* WASM_ENABLE_LINUX_PERF != 0 */