Skip to content

Commit

Permalink
Merge pull request #495 from DataDog/xgouchet/RUMM-1274/track_memory_…
Browse files Browse the repository at this point in the history
…usage

RUMM-1274 Implement Memory reader
  • Loading branch information
xgouchet authored Jun 2, 2021
2 parents 66c0dac + f061e69 commit 999358a
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@
9EEA4871258B76A100EBDA9D /* Global+objc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EEA4870258B76A100EBDA9D /* Global+objc.swift */; };
9EF963E82537556300235F98 /* DDURLSessionDelegateAsSuperclassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF963E72537556300235F98 /* DDURLSessionDelegateAsSuperclassTests.swift */; };
9EFD112C24B32D29003A1A2B /* FirstPartyURLsFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EFD112B24B32D29003A1A2B /* FirstPartyURLsFilter.swift */; };
B3BBBCB2265E71C700943419 /* VitalMemoryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3BBBCB0265E71C600943419 /* VitalMemoryReader.swift */; };
B3BBBCB3265E71C700943419 /* VitalReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3BBBCB1265E71C600943419 /* VitalReader.swift */; };
B3BBBCBC265E71D100943419 /* VitalMemoryReaderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3BBBCBB265E71D100943419 /* VitalMemoryReaderTest.swift */; };
B3FC3C0926526F0000DEED9E /* VitalInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FC3C0626526EFF00DEED9E /* VitalInfo.swift */; };
B3FC3C0A26526F0000DEED9E /* VitalObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FC3C0726526F0000DEED9E /* VitalObserver.swift */; };
B3FC3C332652AE1400DEED9E /* VitalListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3FC3C322652AE1400DEED9E /* VitalListener.swift */; };
Expand Down Expand Up @@ -1054,6 +1057,9 @@
9EF49F17244770AD004F2CA0 /* DatadogIntegrationTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DatadogIntegrationTests.xcconfig; sourceTree = "<group>"; };
9EF963E72537556300235F98 /* DDURLSessionDelegateAsSuperclassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDURLSessionDelegateAsSuperclassTests.swift; sourceTree = "<group>"; };
9EFD112B24B32D29003A1A2B /* FirstPartyURLsFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstPartyURLsFilter.swift; sourceTree = "<group>"; };
B3BBBCB0265E71C600943419 /* VitalMemoryReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalMemoryReader.swift; sourceTree = "<group>"; };
B3BBBCB1265E71C600943419 /* VitalReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalReader.swift; sourceTree = "<group>"; };
B3BBBCBB265E71D100943419 /* VitalMemoryReaderTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalMemoryReaderTest.swift; sourceTree = "<group>"; };
B3FC3C0626526EFF00DEED9E /* VitalInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalInfo.swift; sourceTree = "<group>"; };
B3FC3C0726526F0000DEED9E /* VitalObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VitalObserver.swift; sourceTree = "<group>"; };
B3FC3C322652AE1400DEED9E /* VitalListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VitalListener.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3011,6 +3017,8 @@
B3FC3C0426526EE900DEED9E /* RUMVitals */ = {
isa = PBXGroup;
children = (
B3BBBCB0265E71C600943419 /* VitalMemoryReader.swift */,
B3BBBCB1265E71C600943419 /* VitalReader.swift */,
B3FC3C0626526EFF00DEED9E /* VitalInfo.swift */,
B3FC3C0726526F0000DEED9E /* VitalObserver.swift */,
B3FC3C322652AE1400DEED9E /* VitalListener.swift */,
Expand All @@ -3021,6 +3029,7 @@
B3FC3C1226526F4100DEED9E /* RUMVitals */ = {
isa = PBXGroup;
children = (
B3BBBCBB265E71D100943419 /* VitalMemoryReaderTest.swift */,
B3FC3C3B2653A97700DEED9E /* VitalObserverTest.swift */,
);
path = RUMVitals;
Expand Down Expand Up @@ -3622,6 +3631,7 @@
61B0386C2527247B00518F3C /* TaskInterception.swift in Sources */,
61B03892252724D900518F3C /* HTTPHeadersReader.swift in Sources */,
61122ECE25B1B74500F9C7F5 /* SpanSanitizer.swift in Sources */,
B3BBBCB3265E71C700943419 /* VitalReader.swift in Sources */,
613E79282577B0EE00DFCC17 /* Writer.swift in Sources */,
61B0384E2527246900518F3C /* URLSessionAutoInstrumentation.swift in Sources */,
61C5A88924509A0C00DA608C /* DDSpanContext.swift in Sources */,
Expand Down Expand Up @@ -3691,6 +3701,7 @@
E1D5AEA724B4D45B007F194B /* Versioning.swift in Sources */,
61133BD82423979B00786299 /* HTTPClient.swift in Sources */,
61B038542527246D00518F3C /* URLSessionSwizzler.swift in Sources */,
B3BBBCB2265E71C700943419 /* VitalMemoryReader.swift in Sources */,
61133BDB2423979B00786299 /* DatadogConfiguration.swift in Sources */,
619E16D82577C1CB00B2516B /* DataProcessor.swift in Sources */,
614E9EB3244719FA007EE3E1 /* BundleType.swift in Sources */,
Expand Down Expand Up @@ -3768,6 +3779,7 @@
61E917CF2464270500E6C631 /* EncodableValueTests.swift in Sources */,
61133C542423990D00786299 /* NetworkConnectionInfoProviderTests.swift in Sources */,
616B668E259CC28E00968EE8 /* DDRUMMonitorTests.swift in Sources */,
B3BBBCBC265E71D100943419 /* VitalMemoryReaderTest.swift in Sources */,
9EE5AD8226205B82001E699E /* DDNSURLSessionDelegateTests.swift in Sources */,
6182374325D3DFD5006A375B /* CrashReportingWithRUMIntegrationTests.swift in Sources */,
61B558CF2469561C001460D3 /* LoggerBuilderTests.swift in Sources */,
Expand Down
34 changes: 34 additions & 0 deletions Sources/Datadog/RUM/RUMVitals/VitalMemoryReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-Present Datadog, Inc.
*/

import Foundation

/// A class reading the Virtual Memory resident_size, that is the part of the virtual memory which is currently in RAM.
internal class VitalMemoryReader: VitalReader {
static let task_vm_info_count = MemoryLayout<task_vm_info>.size / MemoryLayout<natural_t>.size

func readVitalData() -> Double? {
var vmInfo = task_vm_info()
var vmInfoSize = mach_msg_type_size_t(VitalMemoryReader.task_vm_info_count)

let kern: kern_return_t = withUnsafeMutablePointer(to: &vmInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
task_info(
mach_task_self_,
task_flavor_t(TASK_VM_INFO),
$0,
&vmInfoSize
)
}
}

if kern == KERN_SUCCESS {
return Double(vmInfo.resident_size)
} else {
return nil
}
}
}
12 changes: 12 additions & 0 deletions Sources/Datadog/RUM/RUMVitals/VitalReader.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-Present Datadog, Inc.
*/

import Foundation

/// A listener getting aggregated information from a VitalObserver
internal protocol VitalReader {
func readVitalData() -> Double?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-Present Datadog, Inc.
*/

import XCTest
@testable import Datadog

internal class VitalMemoryReaderTest: XCTestCase {
func testReadMemory() throws {
let reader = VitalMemoryReader()

let result = reader.readVitalData()

XCTAssertNotNil(result)
}

func testWhenMemoryConsumptionGrows() {
// Given
let reader = VitalMemoryReader()
let threshold = reader.readVitalData()
let allocationSize = 128 * 1_024

// When
let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: allocationSize)
for i in 0..<allocationSize {
(intPointer + i).initialize(to: i)
}
let measure = reader.readVitalData()
intPointer.deallocate()

// Then
// Test that at least half the allocated size is accounted for to mitigate flakiness in memory readings
let expectedAllocatedSize = allocationSize * MemoryLayout<Int>.stride / 2
XCTAssertNotNil(threshold)
XCTAssertNotNil(measure)
let delta = measure! - threshold!
XCTAssertGreaterThanOrEqual(delta, Double(expectedAllocatedSize))
}

func testWhenMemoryConsumptionShrinks() {
// Given
let reader = VitalMemoryReader()
let allocationSize = 128 * 1_024
let intPointer = UnsafeMutablePointer<Int>.allocate(capacity: allocationSize)
for i in 0..<allocationSize {
(intPointer + i).initialize(to: i)
}
let threshold = reader.readVitalData()

// When
intPointer.deallocate()
let measure = reader.readVitalData()

// Then
// Test that at least half the allocated size is accounted for to mitigate flakiness in memory readings
let expectedAllocatedSize = allocationSize * MemoryLayout<Int>.stride / 2
XCTAssertNotNil(threshold)
XCTAssertNotNil(measure)
let delta = threshold! - measure!
XCTAssertGreaterThanOrEqual(delta, Double(expectedAllocatedSize))
}
}

0 comments on commit 999358a

Please sign in to comment.