Skip to content

Commit eb563fa

Browse files
rmacnak-googleCommit Queue
authored and
Commit Queue
committed
[vm, gc] Report RSS as timeline counter events, sampled before and after GC.
Catapult will display a nice graph for this. TEST=view timeline Change-Id: I6b6fdede463b37dbb10841cfa7c1e08c95e7cb62 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/427060 Commit-Queue: Ryan Macnak <[email protected]> Reviewed-by: Slava Egorov <[email protected]>
1 parent 10fddf8 commit eb563fa

File tree

11 files changed

+106
-0
lines changed

11 files changed

+106
-0
lines changed

pkg/vm_service/test/get_vm_timeline_rpc_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ void allEventsHaveIsolateNumber(List<TimelineEvent> events) {
111111
// Skip API category events which sometimes don't have an isolate.
112112
continue;
113113
}
114+
if (event['name'] == 'RSS' && event['ph'] == 'C') {
115+
// Skip RSS events, which don't have an isolate or isolate group.
116+
continue;
117+
}
114118
if (event['cat'] == 'Embedder' &&
115119
(event['name'] == 'DFE::ReadScript' ||
116120
event['name'] == 'CreateIsolateGroupAndSetupHelper' ||

runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ void allEventsHaveIsolateNumber(List events) {
103103
// Skip API category events which sometimes don't have an isolate.
104104
continue;
105105
}
106+
if (event['name'] == 'RSS' && event['ph'] == 'C') {
107+
// Skip RSS events, which don't have an isolate or isolate group.
108+
continue;
109+
}
106110
if (event['cat'] == 'Embedder' &&
107111
(event['name'] == 'DFE::ReadScript' ||
108112
event['name'] == 'CreateIsolateGroupAndSetupHelper')) {

runtime/vm/heap/heap.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,19 @@ void Heap::PrintMemoryUsageJSON(JSONObject* jsobj) const {
10021002
}
10031003
#endif // PRODUCT
10041004

1005+
static void RecordRSS() {
1006+
#if defined(SUPPORT_TIMELINE)
1007+
TimelineEvent* event = Timeline::GetGCStream()->StartEvent();
1008+
if (event != nullptr) {
1009+
event->Counter("RSS");
1010+
event->SetNumArguments(1);
1011+
event->FormatArgument(0, "value", "%" Pd, OS::CurrentRSS());
1012+
event->ClearIsolateGroupId(); // This value is per-process.
1013+
event->Complete();
1014+
}
1015+
#endif
1016+
}
1017+
10051018
void Heap::RecordBeforeGC(GCType type, GCReason reason) {
10061019
stats_.num_++;
10071020
stats_.type_ = type;
@@ -1010,6 +1023,7 @@ void Heap::RecordBeforeGC(GCType type, GCReason reason) {
10101023
stats_.before_.new_ = new_space_.GetCurrentUsage();
10111024
stats_.before_.old_ = old_space_.GetCurrentUsage();
10121025
stats_.before_.store_buffer_ = isolate_group_->store_buffer()->Size();
1026+
RecordRSS();
10131027
}
10141028

10151029
void Heap::RecordAfterGC(GCType type) {
@@ -1025,6 +1039,7 @@ void Heap::RecordAfterGC(GCType type) {
10251039
stats_.after_.new_ = new_space_.GetCurrentUsage();
10261040
stats_.after_.old_ = old_space_.GetCurrentUsage();
10271041
stats_.after_.store_buffer_ = isolate_group_->store_buffer()->Size();
1042+
RecordRSS();
10281043
#ifndef PRODUCT
10291044
// For now we'll emit the same GC events on all isolates.
10301045
if (Service::gc_stream.enabled()) {

runtime/vm/os.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ class OS {
6868
// Returns number of available processor cores.
6969
static int NumberOfAvailableProcessors();
7070

71+
// Returns the current resident set size in bytes, or 0 if it could not be
72+
// determined.
73+
static uintptr_t CurrentRSS();
74+
7175
// Sleep the currently executing thread for millis ms.
7276
static void Sleep(int64_t millis);
7377

runtime/vm/os_android.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,23 @@ int OS::NumberOfAvailableProcessors() {
204204
return sysconf(_SC_NPROCESSORS_ONLN);
205205
}
206206

207+
uintptr_t OS::CurrentRSS() {
208+
// The second value in /proc/self/statm is the current RSS in pages.
209+
// It is not possible to use getrusage() because the interested fields are not
210+
// implemented by the linux kernel.
211+
FILE* statm = fopen("/proc/self/statm", "r");
212+
if (statm == nullptr) {
213+
return 0;
214+
}
215+
int64_t current_rss_pages = 0;
216+
int matches = fscanf(statm, "%*s%" Pd64 "", &current_rss_pages);
217+
fclose(statm);
218+
if (matches != 1) {
219+
return 0;
220+
}
221+
return current_rss_pages * getpagesize();
222+
}
223+
207224
void OS::Sleep(int64_t millis) {
208225
int64_t micros = millis * kMicrosecondsPerMillisecond;
209226
SleepMicros(micros);

runtime/vm/os_fuchsia.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,18 @@ int OS::NumberOfAvailableProcessors() {
488488
return sysconf(_SC_NPROCESSORS_CONF);
489489
}
490490

491+
uintptr_t OS::CurrentRSS() {
492+
zx_info_task_stats_t task_stats;
493+
zx_handle_t process = zx_process_self();
494+
zx_status_t status =
495+
zx_object_get_info(process, ZX_INFO_TASK_STATS, &task_stats,
496+
sizeof(task_stats), nullptr, nullptr);
497+
if (status != ZX_OK) {
498+
return 0;
499+
}
500+
return task_stats.mem_private_bytes + task_stats.mem_shared_bytes;
501+
}
502+
491503
void OS::Sleep(int64_t millis) {
492504
SleepMicros(millis * kMicrosecondsPerMillisecond);
493505
}

runtime/vm/os_linux.cc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,23 @@ int OS::NumberOfAvailableProcessors() {
521521
return sysconf(_SC_NPROCESSORS_ONLN);
522522
}
523523

524+
uintptr_t OS::CurrentRSS() {
525+
// The second value in /proc/self/statm is the current RSS in pages.
526+
// It is not possible to use getrusage() because the interested fields are not
527+
// implemented by the linux kernel.
528+
FILE* statm = fopen("/proc/self/statm", "r");
529+
if (statm == nullptr) {
530+
return 0;
531+
}
532+
int64_t current_rss_pages = 0;
533+
int matches = fscanf(statm, "%*s%" Pd64 "", &current_rss_pages);
534+
fclose(statm);
535+
if (matches != 1) {
536+
return 0;
537+
}
538+
return current_rss_pages * getpagesize();
539+
}
540+
524541
void OS::Sleep(int64_t millis) {
525542
int64_t micros = millis * kMicrosecondsPerMillisecond;
526543
SleepMicros(micros);

runtime/vm/os_macos.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,18 @@ int OS::NumberOfAvailableProcessors() {
123123
return sysconf(_SC_NPROCESSORS_ONLN);
124124
}
125125

126+
uintptr_t OS::CurrentRSS() {
127+
struct mach_task_basic_info info;
128+
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
129+
kern_return_t result =
130+
task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
131+
reinterpret_cast<task_info_t>(&info), &infoCount);
132+
if (result != KERN_SUCCESS) {
133+
return 0;
134+
}
135+
return info.resident_size;
136+
}
137+
126138
void OS::Sleep(int64_t millis) {
127139
int64_t micros = millis * kMicrosecondsPerMillisecond;
128140
SleepMicros(micros);

runtime/vm/os_win.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,22 @@ int OS::NumberOfAvailableProcessors() {
238238
return info.dwNumberOfProcessors;
239239
}
240240

241+
uintptr_t OS::CurrentRSS() {
242+
// Although the documentation at
243+
// https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-getprocessmemoryinfo
244+
// claims that GetProcessMemoryInfo is UWP compatible, it is actually not
245+
// hence this function cannot work when compiled in UWP mode.
246+
#ifdef DART_TARGET_OS_WINDOWS_UWP
247+
return 0;
248+
#else
249+
PROCESS_MEMORY_COUNTERS pmc;
250+
if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
251+
return 0;
252+
}
253+
return pmc.WorkingSetSize;
254+
#endif
255+
}
256+
241257
void OS::Sleep(int64_t millis) {
242258
::Sleep(millis);
243259
}

runtime/vm/timeline.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,10 @@ bool TimelineEvent::HasIsolateGroupId() const {
12201220
return isolate_group_id_ != ILLEGAL_ISOLATE_GROUP_ID;
12211221
}
12221222

1223+
void TimelineEvent::ClearIsolateGroupId() {
1224+
isolate_group_id_ = ILLEGAL_ISOLATE_GROUP_ID;
1225+
}
1226+
12231227
TimelineTrackMetadata::TimelineTrackMetadata(intptr_t pid,
12241228
intptr_t tid,
12251229
CStringUniquePtr&& track_name)

runtime/vm/timeline.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ class TimelineEvent {
457457

458458
bool HasIsolateId() const;
459459
bool HasIsolateGroupId() const;
460+
void ClearIsolateGroupId();
460461

461462
// The lowest time value stored in this event.
462463
int64_t LowTime() const;

0 commit comments

Comments
 (0)