Profile.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include "Profile.h"
  2. #include "ProfileModel.h"
  3. #include <AK/QuickSort.h>
  4. #include <LibCore/CFile.h>
  5. #include <stdio.h>
  6. Profile::Profile(const JsonArray& json, Vector<NonnullRefPtr<ProfileNode>>&& roots, u64 first_timestamp, u64 last_timestamp)
  7. : m_json(json)
  8. , m_roots(move(roots))
  9. , m_first_timestamp(first_timestamp)
  10. , m_last_timestamp(last_timestamp)
  11. {
  12. m_model = ProfileModel::create(*this);
  13. }
  14. Profile::~Profile()
  15. {
  16. }
  17. GModel& Profile::model()
  18. {
  19. return *m_model;
  20. }
  21. OwnPtr<Profile> Profile::load_from_file(const StringView& path)
  22. {
  23. auto file = CFile::construct(path);
  24. if (!file->open(CIODevice::ReadOnly)) {
  25. fprintf(stderr, "Unable to open %s, error: %s\n", String(path).characters(), file->error_string());
  26. return nullptr;
  27. }
  28. auto json = JsonValue::from_string(file->read_all());
  29. if (!json.is_array()) {
  30. fprintf(stderr, "Invalid format (not a JSON array)\n");
  31. return nullptr;
  32. }
  33. auto& samples = json.as_array();
  34. if (samples.is_empty())
  35. return nullptr;
  36. NonnullRefPtrVector<ProfileNode> roots;
  37. auto find_or_create_root = [&roots](const String& symbol, u32 address, u32 offset, u64 timestamp) -> ProfileNode& {
  38. for (int i = 0; i < roots.size(); ++i) {
  39. auto& root = roots[i];
  40. if (root.symbol() == symbol) {
  41. return root;
  42. }
  43. }
  44. auto new_root = ProfileNode::create(symbol, address, offset, timestamp);
  45. roots.append(new_root);
  46. return new_root;
  47. };
  48. u64 first_timestamp = samples.at(0).as_object().get("timestamp").to_number<u64>();
  49. u64 last_timestamp = samples.at(samples.size() - 1).as_object().get("timestamp").to_number<u64>();
  50. samples.for_each([&](const JsonValue& sample) {
  51. auto frames_value = sample.as_object().get("frames");
  52. auto& frames = frames_value.as_array();
  53. ProfileNode* node = nullptr;
  54. for (int i = frames.size() - 1; i >= 0; --i) {
  55. auto& frame = frames.at(i);
  56. auto symbol = frame.as_object().get("symbol").as_string_or({});
  57. auto address = frame.as_object().get("address").as_u32();
  58. auto offset = frame.as_object().get("offset").as_u32();
  59. auto timestamp = frame.as_object().get("timestamp").to_number<u64>();
  60. if (symbol.is_empty())
  61. break;
  62. if (!node)
  63. node = &find_or_create_root(symbol, address, offset, timestamp);
  64. else
  65. node = &node->find_or_create_child(symbol, address, offset, timestamp);
  66. node->increment_sample_count();
  67. }
  68. });
  69. for (auto& root : roots) {
  70. root.sort_children();
  71. }
  72. return NonnullOwnPtr<Profile>(NonnullOwnPtr<Profile>::Adopt, *new Profile(move(samples), move(roots), first_timestamp, last_timestamp));
  73. }
  74. void ProfileNode::sort_children()
  75. {
  76. quick_sort(m_children.begin(), m_children.end(), [](auto& a, auto& b) {
  77. return a->sample_count() >= b->sample_count();
  78. });
  79. for (auto& child : m_children)
  80. child->sort_children();
  81. }