thread_stats_manager.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #ifndef __THREAD_STATS_MANAGER_H
  2. #define __THREAD_STATS_MANAGER_H
  3. #include "fixed_types.h"
  4. #include "subsecond_time.h"
  5. #include "hooks_manager.h"
  6. #include "bottlegraph.h"
  7. class StatsMetricBase;
  8. class ThreadStatsManager
  9. {
  10. public:
  11. typedef UInt32 ThreadStatType;
  12. typedef std::vector<ThreadStatType> ThreadStatTypeList;
  13. enum ThreadStatTypeEnum
  14. {
  15. INSTRUCTIONS,
  16. ELAPSED_NONIDLE_TIME,
  17. WAITING_COST,
  18. NUM_THREAD_STAT_FIXED_TYPES, // Number of fixed thread statistics
  19. DYNAMIC, // User-defined thread statistics
  20. INVALID
  21. };
  22. class ThreadStats
  23. {
  24. public:
  25. const Thread *m_thread;
  26. core_id_t m_core_id;
  27. std::vector<UInt64> time_by_core;
  28. std::vector<UInt64> insn_by_core;
  29. SubsecondTime m_elapsed_time;
  30. SubsecondTime m_unscheduled_time;
  31. ThreadStats(thread_id_t thread_id);
  32. void update(SubsecondTime time, bool init = false); // Update statistics
  33. private:
  34. SubsecondTime m_time_last; // Time of last snapshot
  35. std::unordered_map<ThreadStatType, UInt64> m_counts; // Running total of thread statistics
  36. std::unordered_map<ThreadStatType, UInt64> m_last; // Snapshot of core's statistics when we last updated m_current
  37. friend class ThreadStatsManager;
  38. };
  39. typedef UInt64 (*ThreadStatCallback)(ThreadStatType type, thread_id_t thread_id, Core *core, UInt64 user);
  40. ThreadStatsManager();
  41. ~ThreadStatsManager();
  42. // Thread statistics are updated lazily (on thread move and before statistics writing),
  43. // call this function to force an update before reading
  44. void update(thread_id_t thread_id = INVALID_THREAD_ID, SubsecondTime time = SubsecondTime::MaxTime());
  45. void calculateWaitingCosts(SubsecondTime time);
  46. const ThreadStatTypeList& getThreadStatTypes() { return m_thread_stat_types; }
  47. const char* getThreadStatName(ThreadStatType type) { return m_thread_stat_callbacks[type].m_name; }
  48. UInt64 getThreadStatistic(thread_id_t thread_id, ThreadStatType type) { return m_threads_stats[thread_id]->m_counts[type]; }
  49. ThreadStatType registerThreadStatMetric(ThreadStatType type, const char* name, ThreadStatCallback func, UInt64 user);
  50. private:
  51. struct StatCallback {
  52. const char* m_name;
  53. ThreadStatCallback m_func;
  54. UInt64 m_user;
  55. StatCallback() {};
  56. StatCallback(const char* name, ThreadStatCallback func, UInt64 user) : m_name(name), m_func(func), m_user(user) {}
  57. UInt64 call(ThreadStatType type, thread_id_t thread_id, Core *core) { return m_func(type, thread_id, core, m_user); }
  58. };
  59. // Make sure m_threads_stats is statically allocated, as we may do inserts and reads simultaneously
  60. // which does not work on an unordered_map
  61. static const int MAX_THREADS = 4096;
  62. std::vector<ThreadStats*> m_threads_stats;
  63. ThreadStatTypeList m_thread_stat_types;
  64. std::unordered_map<ThreadStatType, StatCallback> m_thread_stat_callbacks;
  65. ThreadStatType m_next_dynamic_type;
  66. BottleGraphManager m_bottlegraphs;
  67. SubsecondTime m_waiting_time_last;
  68. static UInt64 metricCallback(ThreadStatType type, thread_id_t thread_id, Core *core, UInt64 user);
  69. UInt64 callThreadStatCallback(ThreadStatType type, thread_id_t thread_id, Core *core);
  70. void pre_stat_write();
  71. void threadCreate(thread_id_t thread_id);
  72. void threadStart(thread_id_t thread_id, SubsecondTime time);
  73. void threadStall(thread_id_t thread_id, ThreadManager::stall_type_t reason, SubsecondTime time);
  74. void threadResume(thread_id_t thread_id, thread_id_t thread_by, SubsecondTime time);
  75. void threadExit(thread_id_t thread_id, SubsecondTime time);
  76. // Hook stubs
  77. static SInt64 hook_pre_stat_write(UInt64 ptr, UInt64)
  78. { ((ThreadStatsManager*)ptr)->pre_stat_write(); return 0; }
  79. static SInt64 hook_thread_create(UInt64 ptr, UInt64 _args)
  80. {
  81. HooksManager::ThreadCreate *args = (HooksManager::ThreadCreate *)_args;
  82. ((ThreadStatsManager*)ptr)->threadCreate(args->thread_id);
  83. return 0;
  84. }
  85. static SInt64 hook_thread_start(UInt64 ptr, UInt64 _args)
  86. {
  87. HooksManager::ThreadTime *args = (HooksManager::ThreadTime *)_args;
  88. ((ThreadStatsManager*)ptr)->threadStart(args->thread_id, args->time);
  89. return 0;
  90. }
  91. static SInt64 hook_thread_stall(UInt64 ptr, UInt64 _args)
  92. {
  93. HooksManager::ThreadStall *args = (HooksManager::ThreadStall *)_args;
  94. ((ThreadStatsManager*)ptr)->threadStall(args->thread_id, args->reason, args->time);
  95. return 0;
  96. }
  97. static SInt64 hook_thread_resume(UInt64 ptr, UInt64 _args)
  98. {
  99. HooksManager::ThreadResume *args = (HooksManager::ThreadResume *)_args;
  100. ((ThreadStatsManager*)ptr)->threadResume(args->thread_id, args->thread_by, args->time);
  101. return 0;
  102. }
  103. static SInt64 hook_thread_exit(UInt64 ptr, UInt64 _args)
  104. {
  105. HooksManager::ThreadTime *args = (HooksManager::ThreadTime *)_args;
  106. ((ThreadStatsManager*)ptr)->threadExit(args->thread_id, args->time);
  107. return 0;
  108. }
  109. };
  110. // Helper class to register named statistics objects as per-thread statistics.
  111. // Caches the StatsMetricBase objects to avoid the string lookups on every access.
  112. class ThreadStatNamedStat
  113. {
  114. public:
  115. static ThreadStatsManager::ThreadStatType registerStat(const char* name, String objectName, String metricName);
  116. private:
  117. std::vector<StatsMetricBase*> m_stats;
  118. ThreadStatNamedStat(String objectName, String metricName);
  119. static UInt64 callback(ThreadStatsManager::ThreadStatType type, thread_id_t thread_id, Core *core, UInt64 user);
  120. };
  121. #endif // __THREAD_STATS_MANAGER_H