FPRMemoryGaugeCollector.m 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // Copyright 2020 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector.h"
  15. #import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeCollector+Private.h"
  16. #import "FirebasePerformance/Sources/AppActivity/FPRSessionManager.h"
  17. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
  18. #import "FirebasePerformance/Sources/FPRConsoleLogger.h"
  19. #include <malloc/malloc.h>
  20. @interface FPRMemoryGaugeCollector ()
  21. /** @brief Timer property used for the frequency of CPU data collection. */
  22. @property(nonatomic) dispatch_source_t timerSource;
  23. /** @brief Gauge collector queue on which the gauge data collected. */
  24. @property(nonatomic) dispatch_queue_t gaugeCollectorQueue;
  25. /** @brief Boolean to see if the timer is active or paused. */
  26. @property(nonatomic) BOOL timerPaused;
  27. @end
  28. FPRMemoryGaugeData *fprCollectMemoryMetric() {
  29. NSDate *collectionTime = [NSDate date];
  30. struct mstats ms = mstats();
  31. FPRMemoryGaugeData *gaugeData = [[FPRMemoryGaugeData alloc] initWithCollectionTime:collectionTime
  32. heapUsed:ms.bytes_used
  33. heapAvailable:ms.bytes_free];
  34. return gaugeData;
  35. }
  36. @implementation FPRMemoryGaugeCollector
  37. - (instancetype)initWithDelegate:(id<FPRMemoryGaugeCollectorDelegate>)delegate {
  38. self = [super init];
  39. if (self) {
  40. _delegate = delegate;
  41. _gaugeCollectorQueue =
  42. dispatch_queue_create("com.google.firebase.FPRMemoryGaugeCollector", DISPATCH_QUEUE_SERIAL);
  43. _configurations = [FPRConfigurations sharedInstance];
  44. _timerPaused = YES;
  45. [self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
  46. .applicationState];
  47. }
  48. return self;
  49. }
  50. - (void)stopCollecting {
  51. if (self.timerPaused == NO) {
  52. dispatch_source_cancel(self.timerSource);
  53. self.timerPaused = YES;
  54. }
  55. }
  56. - (void)resumeCollecting {
  57. [self updateSamplingFrequencyForApplicationState:[FPRAppActivityTracker sharedInstance]
  58. .applicationState];
  59. }
  60. - (void)updateSamplingFrequencyForApplicationState:(FPRApplicationState)applicationState {
  61. uint32_t frequencyInMs = (applicationState == FPRApplicationStateBackground)
  62. ? [self.configurations memorySamplingFrequencyInBackgroundInMS]
  63. : [self.configurations memorySamplingFrequencyInForegroundInMS];
  64. [self captureMemoryGaugeAtFrequency:frequencyInMs];
  65. }
  66. #pragma mark - Internal methods.
  67. /**
  68. * Captures the memory gauge at a defined frequency.
  69. *
  70. * @param frequencyInMs Frequency at which the memory gauges are collected.
  71. */
  72. - (void)captureMemoryGaugeAtFrequency:(uint32_t)frequencyInMs {
  73. [self stopCollecting];
  74. if (frequencyInMs > 0) {
  75. self.timerSource =
  76. dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.gaugeCollectorQueue);
  77. dispatch_source_set_timer(self.timerSource,
  78. dispatch_time(DISPATCH_TIME_NOW, frequencyInMs * NSEC_PER_MSEC),
  79. frequencyInMs * NSEC_PER_MSEC, (1ull * NSEC_PER_SEC) / 10);
  80. FPRMemoryGaugeCollector __weak *weakSelf = self;
  81. dispatch_source_set_event_handler(weakSelf.timerSource, ^{
  82. FPRMemoryGaugeCollector *strongSelf = weakSelf;
  83. if (strongSelf) {
  84. [strongSelf collectMetric];
  85. }
  86. });
  87. dispatch_resume(self.timerSource);
  88. self.timerPaused = NO;
  89. } else {
  90. FPRLogDebug(kFPRMemoryCollection, @"Memory metric collection is disabled.");
  91. }
  92. }
  93. - (void)collectMetric {
  94. FPRMemoryGaugeData *gaugeMetric = fprCollectMemoryMetric();
  95. [self.delegate memoryGaugeCollector:self gaugeData:gaugeMetric];
  96. }
  97. @end