jdk

Форк
0
/
memoryFileTracker.cpp 
203 строки · 7.7 Кб
1
/*
2
 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
 *
5
 * This code is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License version 2 only, as
7
 * published by the Free Software Foundation.
8
 *
9
 * This code is distributed in the hope that it will be useful, but WITHOUT
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12
 * version 2 for more details (a copy is included in the LICENSE file that
13
 * accompanied this code).
14
 *
15
 * You should have received a copy of the GNU General Public License version
16
 * 2 along with this work; if not, write to the Free Software Foundation,
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
 *
19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
 * or visit www.oracle.com if you need additional information or have any
21
 * questions.
22
 *
23
 */
24

25
#include "precompiled.hpp"
26
#include "memory/allocation.hpp"
27
#include "nmt/memTracker.hpp"
28
#include "nmt/memoryFileTracker.hpp"
29
#include "nmt/nmtCommon.hpp"
30
#include "nmt/nmtNativeCallStackStorage.hpp"
31
#include "nmt/vmatree.hpp"
32
#include "runtime/mutex.hpp"
33
#include "utilities/growableArray.hpp"
34
#include "utilities/nativeCallStack.hpp"
35
#include "utilities/ostream.hpp"
36

37
MemoryFileTracker* MemoryFileTracker::Instance::_tracker = nullptr;
38
PlatformMutex* MemoryFileTracker::Instance::_mutex = nullptr;
39

40
MemoryFileTracker::MemoryFileTracker(bool is_detailed_mode)
41
  : _stack_storage(is_detailed_mode), _files() {}
42

43
void MemoryFileTracker::allocate_memory(MemoryFile* file, size_t offset,
44
                                        size_t size, const NativeCallStack& stack,
45
                                        MEMFLAGS flag) {
46
  NativeCallStackStorage::StackIndex sidx = _stack_storage.push(stack);
47
  VMATree::RegionData regiondata(sidx, flag);
48
  VMATree::SummaryDiff diff = file->_tree.commit_mapping(offset, size, regiondata);
49
  for (int i = 0; i < mt_number_of_types; i++) {
50
    VirtualMemory* summary = file->_summary.by_type(NMTUtil::index_to_flag(i));
51
    summary->reserve_memory(diff.flag[i].commit);
52
    summary->commit_memory(diff.flag[i].commit);
53
  }
54
}
55

56
void MemoryFileTracker::free_memory(MemoryFile* file, size_t offset, size_t size) {
57
  VMATree::SummaryDiff diff = file->_tree.release_mapping(offset, size);
58
  for (int i = 0; i < mt_number_of_types; i++) {
59
    VirtualMemory* summary = file->_summary.by_type(NMTUtil::index_to_flag(i));
60
    summary->reserve_memory(diff.flag[i].commit);
61
    summary->commit_memory(diff.flag[i].commit);
62
  }
63
}
64

65
void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* stream, size_t scale) {
66
  assert(MemTracker::tracking_level() == NMT_detail, "must");
67

68
  stream->print_cr("Memory map of %s", file->_descriptive_name);
69
  stream->cr();
70
  VMATree::TreapNode* prev = nullptr;
71
#ifdef ASSERT
72
  VMATree::TreapNode* broken_start = nullptr;
73
  VMATree::TreapNode* broken_end = nullptr;
74
#endif
75
  file->_tree.visit_in_order([&](VMATree::TreapNode* current) {
76
    if (prev == nullptr) {
77
      // Must be first node.
78
      prev = current;
79
      return;
80
    }
81
#ifdef ASSERT
82
    if (broken_start != nullptr && prev->val().out.type() != current->val().in.type()) {
83
      broken_start = prev;
84
      broken_end = current;
85
    }
86
#endif
87
    if (prev->val().out.type() == VMATree::StateType::Committed) {
88
      const VMATree::position& start_addr = prev->key();
89
      const VMATree::position& end_addr = current->key();
90
      stream->print_cr("[" PTR_FORMAT " - " PTR_FORMAT "] allocated " SIZE_FORMAT "%s" " for %s from",
91
                       start_addr, end_addr,
92
                       NMTUtil::amount_in_scale(end_addr - start_addr, scale),
93
                       NMTUtil::scale_name(scale),
94
                       NMTUtil::flag_to_name(prev->val().out.flag()));
95
      {
96
        streamIndentor si(stream, 4);
97
        _stack_storage.get(prev->val().out.stack()).print_on(stream);
98
      }
99
      stream->cr();
100
    }
101
    prev = current;
102
  });
103
#ifdef ASSERT
104
  if (broken_start != nullptr) {
105
    tty->print_cr("Broken tree found with first occurrence at nodes %zu, %zu",
106
                  broken_start->key(), broken_end->key());
107
    tty->print_cr("Expected start out to have same type as end in, but was: %s, %s",
108
                  VMATree::statetype_to_string(broken_start->val().out.type()),
109
                  VMATree::statetype_to_string(broken_end->val().in.type()));
110
  }
111
#endif
112
}
113

114
MemoryFileTracker::MemoryFile* MemoryFileTracker::make_file(const char* descriptive_name) {
115
  MemoryFile* file_place = new MemoryFile{descriptive_name};
116
  _files.push(file_place);
117
  return file_place;
118
}
119

120
void MemoryFileTracker::free_file(MemoryFile* file) {
121
  if (file == nullptr) return;
122
  _files.remove(file);
123
  delete file;
124
}
125

126
const GrowableArrayCHeap<MemoryFileTracker::MemoryFile*, mtNMT>& MemoryFileTracker::files() {
127
  return _files;
128
}
129

130
bool MemoryFileTracker::Instance::initialize(NMT_TrackingLevel tracking_level) {
131
  if (tracking_level == NMT_TrackingLevel::NMT_off) return true;
132
  _tracker = static_cast<MemoryFileTracker*>(os::malloc(sizeof(MemoryFileTracker), mtNMT));
133
  if (_tracker == nullptr) return false;
134
  new (_tracker) MemoryFileTracker(tracking_level == NMT_TrackingLevel::NMT_detail);
135
  _mutex = new PlatformMutex();
136
  return true;
137
}
138

139
void MemoryFileTracker::Instance::allocate_memory(MemoryFile* file, size_t offset,
140
                                                  size_t size, const NativeCallStack& stack,
141
                                                  MEMFLAGS flag) {
142
  _tracker->allocate_memory(file, offset, size, stack, flag);
143
}
144

145
void MemoryFileTracker::Instance::free_memory(MemoryFile* file, size_t offset, size_t size) {
146
  _tracker->free_memory(file, offset, size);
147
}
148

149
MemoryFileTracker::MemoryFile*
150
MemoryFileTracker::Instance::make_file(const char* descriptive_name) {
151
  return _tracker->make_file(descriptive_name);
152
}
153

154
void MemoryFileTracker::Instance::free_file(MemoryFileTracker::MemoryFile* file) {
155
  return _tracker->free_file(file);
156
}
157

158
void MemoryFileTracker::Instance::print_report_on(const MemoryFile* file,
159
                                                  outputStream* stream, size_t scale) {
160
  assert(file != nullptr, "must be");
161
  assert(stream != nullptr, "must be");
162
  _tracker->print_report_on(file, stream, scale);
163
}
164

165
void MemoryFileTracker::Instance::print_all_reports_on(outputStream* stream, size_t scale) {
166
  const GrowableArrayCHeap<MemoryFileTracker::MemoryFile*, mtNMT>& files =
167
      MemoryFileTracker::Instance::files();
168
  stream->cr();
169
  stream->print_cr("Memory file details");
170
  stream->cr();
171
  for (int i = 0; i < files.length(); i++) {
172
    MemoryFileTracker::MemoryFile* file = files.at(i);
173
    MemoryFileTracker::Instance::print_report_on(file, stream, scale);
174
  }
175
}
176

177
const GrowableArrayCHeap<MemoryFileTracker::MemoryFile*, mtNMT>& MemoryFileTracker::Instance::files() {
178
  return _tracker->files();
179
};
180

181
void MemoryFileTracker::summary_snapshot(VirtualMemorySnapshot* snapshot) const {
182
  for (int d = 0; d < _files.length(); d++) {
183
    const MemoryFile* file = _files.at(d);
184
    for (int i = 0; i < mt_number_of_types; i++) {
185
      VirtualMemory* snap = snapshot->by_type(NMTUtil::index_to_flag(i));
186
      const VirtualMemory* current = file->_summary.by_type(NMTUtil::index_to_flag(i));
187
      // Only account the committed memory.
188
      snap->commit_memory(current->committed());
189
    }
190
  }
191
}
192

193
void MemoryFileTracker::Instance::summary_snapshot(VirtualMemorySnapshot* snapshot) {
194
  _tracker->summary_snapshot(snapshot);
195
}
196

197
MemoryFileTracker::Instance::Locker::Locker() {
198
  MemoryFileTracker::Instance::_mutex->lock();
199
}
200

201
MemoryFileTracker::Instance::Locker::~Locker() {
202
  MemoryFileTracker::Instance::_mutex->unlock();
203
}
204

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.