From 27c33f0c55514420038e61ffe304015a631cb87b Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Fri, 15 Nov 2024 09:44:28 +0100 Subject: [PATCH 1/2] impr: Speed up getBinaryImages V2 Follow up on GH-4435. Use binary image cache to get debug meta when finishing the tracer and capturing profiles. Mark all methods to get debug meta not using the cache as deprecated to ensure we migrate to the methods using the cache. --- CHANGELOG.md | 4 ++ Sentry.xcodeproj/project.pbxproj | 6 +-- .../SentryTestUtils-ObjC-BridgingHeader.h | 2 + SentryTestUtils/TestDebugImageProvider.swift | 36 +++++++++++++ Sources/Sentry/PrivateSentrySDKOnly.mm | 3 ++ .../Profiling/SentryProfilerSerialization.mm | 9 ++-- .../Sentry/Public/SentryDebugImageProvider.h | 15 ++++-- Sources/Sentry/SentryBinaryImageCache.m | 11 ++++ Sources/Sentry/SentryDebugImageProvider.m | 49 +++++++++++++----- Sources/Sentry/SentryTracer.m | 2 +- .../HybridPublic/SentryBinaryImageCache.h | 2 + .../SentryDebugImageProvider+HybridSDKs.h | 3 ++ .../SentryProfileTestFixture.swift | 13 +++++ .../Helper/TestDebugImageProvider.swift | 27 ---------- .../PrivateSentrySDKOnlyTests.swift | 27 +++++++++- .../SentryBinaryImageCacheTests.swift | 28 +++++++++++ .../SentryDebugImageProviderTests.swift | 50 +++++++++++++++++++ .../Transaction/SentryTracerTests.swift | 4 +- 18 files changed, 239 insertions(+), 52 deletions(-) create mode 100644 SentryTestUtils/TestDebugImageProvider.swift delete mode 100644 Tests/SentryTests/Helper/TestDebugImageProvider.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd37b4c013..da767b2c0d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ - Make `Scope.span` fully thread safe (#4519) - Finish TTFD when not calling reportFullyDisplayed before binding a new transaction to the scope (#4526). +### Improvements + +- impr: Speed up getBinaryImages V2 (#4539). Follow up on (#4435) + ## 8.40.1 ### Fixes diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index bf4a5fcb6fe..a42f511d1f4 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -76,6 +76,7 @@ 620203B22C59025E0008317C /* SentryFileContents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620203B12C59025E0008317C /* SentryFileContents.swift */; }; 620379DB2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h in Headers */ = {isa = PBXBuildFile; fileRef = 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */; }; 620379DD2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m in Sources */ = {isa = PBXBuildFile; fileRef = 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */; }; + 6205B4A42CE73AA100744684 /* TestDebugImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85790282976A69F00C6AC1F /* TestDebugImageProvider.swift */; }; 621AE74B2C626C230012E730 /* SentryANRTrackerV2.h in Headers */ = {isa = PBXBuildFile; fileRef = 621AE74A2C626C230012E730 /* SentryANRTrackerV2.h */; }; 621AE74D2C626C510012E730 /* SentryANRTrackerV2.m in Sources */ = {isa = PBXBuildFile; fileRef = 621AE74C2C626C510012E730 /* SentryANRTrackerV2.m */; }; 621C88482CAD23B9000EABCB /* SentryCaptureTransactionWithProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 621C88472CAD23B9000EABCB /* SentryCaptureTransactionWithProfile.h */; }; @@ -834,7 +835,6 @@ D855AD62286ED6A4002573E1 /* SentryCrashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D855AD61286ED6A4002573E1 /* SentryCrashTests.m */; }; D855B3E827D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D855B3E727D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift */; }; D855B3EA27D652C700BCED76 /* TestCoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D855B3E927D652C700BCED76 /* TestCoreDataStack.swift */; }; - D85790292976A69F00C6AC1F /* TestDebugImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85790282976A69F00C6AC1F /* TestDebugImageProvider.swift */; }; D85852B627ECEEDA00C6D8AE /* SentryScreenshot.m in Sources */ = {isa = PBXBuildFile; fileRef = D85852B427ECEEDA00C6D8AE /* SentryScreenshot.m */; }; D85852BA27EDDC5900C6D8AE /* SentryUIApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = D85852B827EDDC5900C6D8AE /* SentryUIApplication.m */; }; D858FA662A29EAB3002A3503 /* SentryBinaryImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D858FA642A29EAB3002A3503 /* SentryBinaryImageCache.h */; }; @@ -3069,7 +3069,6 @@ 7B2A70DE27D60904008B0D15 /* SentryTestThreadWrapper.swift */, 7B18DE4928DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift */, 84A8892028DBD8D600C51DFD /* SentryDeviceTests.mm */, - D85790282976A69F00C6AC1F /* TestDebugImageProvider.swift */, 8431EE5A29ADB8EA00D8DC56 /* SentryTimeTests.m */, 62C3168A2B1F865A000D7031 /* SentryTimeSwiftTests.swift */, 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */, @@ -3487,6 +3486,7 @@ 8E25C97425F8511A00DC215B /* TestRandom.swift */, 7BE3C7762445E50A00A38442 /* TestCurrentDateProvider.swift */, 7BDB03BE25136A7D00BAE198 /* TestSentryDispatchQueueWrapper.swift */, + D85790282976A69F00C6AC1F /* TestDebugImageProvider.swift */, 7BAF3DC7243DB90E008A5414 /* TestTransport.swift */, 7BA0C049280563AA003E0326 /* TestTransportAdapter.swift */, 7B944FAF2469B46000A10721 /* TestClient.swift */, @@ -4859,7 +4859,6 @@ 62F05D2B2C0DB1F100916E3F /* SentryLogTestHelper.m in Sources */, 7B68345128F7EB3D00FB7064 /* SentryMeasurementUnitTests.swift in Sources */, 7B14089A248791660035403D /* SentryCrashStackEntryMapperTests.swift in Sources */, - D85790292976A69F00C6AC1F /* TestDebugImageProvider.swift in Sources */, 7B869EBC249B91D8004F4FDB /* SentryDebugMetaEquality.swift in Sources */, 7B01CE3D271993AC00B5AF31 /* SentryTransportFactoryTests.swift in Sources */, 7B30B68026527C3C006B2752 /* SentryFramesTrackerTests.swift in Sources */, @@ -5136,6 +5135,7 @@ 84A5D75B29D5170700388BFA /* TimeInterval+Sentry.swift in Sources */, 62AB8C9E2BF3925700BFC2AC /* WeakReference.swift in Sources */, 84AC61D929F7643B009EEF61 /* TestDispatchFactory.swift in Sources */, + 6205B4A42CE73AA100744684 /* TestDebugImageProvider.swift in Sources */, 8431F01929B2852D00D8DC56 /* Invocation.swift in Sources */, 84B7FA4629B2935F00AD93B1 /* ClearTestState.swift in Sources */, 84281C622A579D0700EE88F2 /* SentryProfilerMocksSwiftCompatible.mm in Sources */, diff --git a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h index 5696b8d04af..e7954cf0ada 100644 --- a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h +++ b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h @@ -27,6 +27,7 @@ #import "PrivateSentrySDKOnly.h" #import "SentryAppStartMeasurement.h" #import "SentryAppState.h" +#import "SentryBinaryImageCache.h" #import "SentryClient+Private.h" #import "SentryClient+TestInit.h" #import "SentryCrash+Test.h" @@ -34,6 +35,7 @@ #import "SentryCrashInstallation+Private.h" #import "SentryCrashMonitor_MachException.h" #import "SentryCrashWrapper.h" +#import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDependencyContainer.h" #import "SentryDispatchFactory.h" #import "SentryDispatchSourceWrapper.h" diff --git a/SentryTestUtils/TestDebugImageProvider.swift b/SentryTestUtils/TestDebugImageProvider.swift new file mode 100644 index 00000000000..e55ae556ec6 --- /dev/null +++ b/SentryTestUtils/TestDebugImageProvider.swift @@ -0,0 +1,36 @@ +import _SentryPrivate +import Foundation +@testable import Sentry + +public class TestDebugImageProvider: SentryDebugImageProvider { + public var debugImages: [DebugMeta]? + + @available(*, deprecated) + public override func getDebugImages() -> [DebugMeta] { + getDebugImagesCrashed(true) + } + + @available(*, deprecated) + public override func getDebugImagesCrashed(_ isCrash: Bool) -> [DebugMeta] { + debugImages ?? super.getDebugImagesCrashed(isCrash) + } + + public var getDebugImagesFromCacheForFramesInvocations = Invocations() + public override func getDebugImagesFromCacheForFrames(frames: [Frame]) -> [DebugMeta] { + getDebugImagesFromCacheForFramesInvocations.record(Void()) + + return debugImages ?? super.getDebugImagesFromCacheForFrames(frames: frames) + } + + public var getDebugImagesFromCacheForThreadsInvocations = Invocations() + public override func getDebugImagesFromCacheForThreads(threads: [SentryThread]) -> [DebugMeta] { + getDebugImagesFromCacheForThreadsInvocations.record(Void()) + return debugImages ?? super.getDebugImagesFromCacheForThreads(threads: threads) + } + + public var getDebugImagesFromCacheInvocations = Invocations() + public override func getDebugImagesFromCache() -> [DebugMeta] { + getDebugImagesFromCacheInvocations.record(Void()) + return debugImages ?? super.getDebugImagesFromCache() + } +} diff --git a/Sources/Sentry/PrivateSentrySDKOnly.mm b/Sources/Sentry/PrivateSentrySDKOnly.mm index 5604cd0deaf..e1a04912632 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.mm +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -60,8 +60,11 @@ + (nullable SentryEnvelope *)envelopeWithData:(NSData *)data + (NSArray *)getDebugImagesCrashed:(BOOL)isCrash { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" return [[SentryDependencyContainer sharedInstance].debugImageProvider getDebugImagesCrashed:isCrash]; +#pragma clang diagnostic pop } + (nullable SentryAppStartMeasurement *)appStartMeasurement diff --git a/Sources/Sentry/Profiling/SentryProfilerSerialization.mm b/Sources/Sentry/Profiling/SentryProfilerSerialization.mm index a2335a68303..66f83d224f3 100644 --- a/Sources/Sentry/Profiling/SentryProfilerSerialization.mm +++ b/Sources/Sentry/Profiling/SentryProfilerSerialization.mm @@ -4,6 +4,7 @@ # import "SentryClient+Private.h" # import "SentryDateUtils.h" +# import "SentryDebugImageProvider+HybridSDKs.h" # import "SentryDependencyContainer.h" # import "SentryDevice.h" # import "SentryEnvelope.h" @@ -312,7 +313,7 @@ const auto chunkID = [[SentryId alloc] init]; const auto payload = sentry_serializedContinuousProfileChunk( profileID, chunkID, profileState, metricProfilerState, - [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesCrashed:NO], + [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesFromCache], SentrySDK.currentHub # if SENTRY_HAS_UIKIT , @@ -350,12 +351,14 @@ SentryProfiler *profiler, NSDictionary *profilingData, SentryTransaction *transaction, NSDate *startTimestamp) { + const auto images = + [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesFromCache]; const auto payload = sentry_serializedTraceProfileData( profilingData, transaction.startSystemTime, transaction.endSystemTime, sentry_profilerTruncationReasonName(profiler.truncationReason), [profiler.metricProfiler serializeTraceProfileMetricsBetween:transaction.startSystemTime and:transaction.endSystemTime], - [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesCrashed:NO], hub + images, hub # if SENTRY_HAS_UIKIT , profiler.screenFrameData @@ -403,7 +406,7 @@ endSystemTime, sentry_profilerTruncationReasonName(profiler.truncationReason), [profiler.metricProfiler serializeTraceProfileMetricsBetween:startSystemTime and:endSystemTime], - [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesCrashed:NO], hub + [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesFromCache], hub # if SENTRY_HAS_UIKIT , profiler.screenFrameData diff --git a/Sources/Sentry/Public/SentryDebugImageProvider.h b/Sources/Sentry/Public/SentryDebugImageProvider.h index 12c3f08a0c3..e5c23647020 100644 --- a/Sources/Sentry/Public/SentryDebugImageProvider.h +++ b/Sources/Sentry/Public/SentryDebugImageProvider.h @@ -31,7 +31,10 @@ NS_ASSUME_NONNULL_BEGIN * crash, each image's data section crash info is also included. */ - (NSArray *)getDebugImagesForThreads:(NSArray *)threads - isCrash:(BOOL)isCrash; + isCrash:(BOOL)isCrash + DEPRECATED_MSG_ATTRIBUTE("This method is slow and will be removed in a future version. Use " + "-[getDebugImagesFromCacheForThreads:] instead."); +; /** * Returns a list of debug images that are being referenced by the given frames. @@ -52,7 +55,9 @@ NS_ASSUME_NONNULL_BEGIN * crash, each image's data section crash info is also included. */ - (NSArray *)getDebugImagesForFrames:(NSArray *)frames - isCrash:(BOOL)isCrash; + isCrash:(BOOL)isCrash + DEPRECATED_MSG_ATTRIBUTE("This method is slow and will be removed in a future version. Use " + "-[getDebugImagesFromCacheForFrames:] instead."); /** * Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually @@ -71,8 +76,12 @@ NS_ASSUME_NONNULL_BEGIN * @param isCrash @c YES if we're collecting binary images for a crash report, @c NO if we're * gathering them for other backtrace information, like a performance transaction. If this is for a * crash, each image's data section crash info is also included. + * + * @warning This method is slow. Please consider using @c getDebugImagesFromCache. */ -- (NSArray *)getDebugImagesCrashed:(BOOL)isCrash; +- (NSArray *)getDebugImagesCrashed:(BOOL)isCrash + DEPRECATED_MSG_ATTRIBUTE("This method is slow and will be removed in a future version. Use " + "-[getDebugImagesFromCache:] instead."); @end diff --git a/Sources/Sentry/SentryBinaryImageCache.m b/Sources/Sentry/SentryBinaryImageCache.m index fa030edf8bd..a89bad69e2c 100644 --- a/Sources/Sentry/SentryBinaryImageCache.m +++ b/Sources/Sentry/SentryBinaryImageCache.m @@ -5,6 +5,8 @@ #import "SentryInAppLogic.h" #import "SentryLog.h" +NS_ASSUME_NONNULL_BEGIN + static void binaryImageWasAdded(const SentryCrashBinaryImage *image); static void binaryImageWasRemoved(const SentryCrashBinaryImage *image); @@ -155,6 +157,13 @@ - (NSInteger)indexOfImage:(uint64_t)address return imagePaths; } +- (NSArray *)getAllBinaryImages +{ + @synchronized(self) { + return _cache.copy; + } +} + @end static void @@ -168,3 +177,5 @@ - (NSInteger)indexOfImage:(uint64_t)address { [SentryDependencyContainer.sharedInstance.binaryImageCache binaryImageRemoved:image]; } + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryDebugImageProvider.m b/Sources/Sentry/SentryDebugImageProvider.m index f12f908629c..f55ae8cab0b 100644 --- a/Sources/Sentry/SentryDebugImageProvider.m +++ b/Sources/Sentry/SentryDebugImageProvider.m @@ -13,6 +13,8 @@ #import "SentryThread.h" #import +NS_ASSUME_NONNULL_BEGIN + @interface SentryDebugImageProvider () @property (nonatomic, strong) id binaryImageProvider; @@ -50,7 +52,10 @@ - (instancetype)initWithBinaryImageProvider:(id) { NSMutableArray *result = [NSMutableArray array]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" NSArray *binaryImages = [self getDebugImagesCrashed:isCrash]; +#pragma clang diagnostic pop for (SentryDebugMeta *sourceImage in binaryImages) { if ([addresses containsObject:sourceImage.imageAddress]) { @@ -134,19 +139,7 @@ - (void)extractDebugImageAddressFromFrames:(NSArray *)frames continue; } - SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init]; - debugMeta.debugID = info.UUID; - debugMeta.type = SentryDebugImageType; - - if (info.vmAddress > 0) { - debugMeta.imageVmAddress = sentry_formatHexAddressUInt64(info.vmAddress); - } - - debugMeta.imageAddress = sentry_formatHexAddressUInt64(info.address); - debugMeta.imageSize = @(info.size); - debugMeta.codeFile = info.name; - - [result addObject:debugMeta]; + [result addObject:[self fillDebugMetaFromBinaryImageInfo:info]]; } return result; @@ -158,6 +151,17 @@ - (void)extractDebugImageAddressFromFrames:(NSArray *)frames return [self getDebugImagesCrashed:YES]; } +- (NSArray *)getDebugImagesFromCache +{ + NSArray *infos = [self.binaryImageCache getAllBinaryImages]; + NSMutableArray *result = + [[NSMutableArray alloc] initWithCapacity:infos.count]; + for (SentryBinaryImageInfo *info in infos) { + [result addObject:[self fillDebugMetaFromBinaryImageInfo:info]]; + } + return result; +} + - (NSArray *)getDebugImagesCrashed:(BOOL)isCrash { NSMutableArray *debugMetaArray = [NSMutableArray new]; @@ -193,4 +197,23 @@ - (SentryDebugMeta *)fillDebugMetaFrom:(SentryCrashBinaryImage)image return debugMeta; } +- (SentryDebugMeta *)fillDebugMetaFromBinaryImageInfo:(SentryBinaryImageInfo *)info +{ + SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init]; + debugMeta.debugID = info.UUID; + debugMeta.type = SentryDebugImageType; + + if (info.vmAddress > 0) { + debugMeta.imageVmAddress = sentry_formatHexAddressUInt64(info.vmAddress); + } + + debugMeta.imageAddress = sentry_formatHexAddressUInt64(info.address); + debugMeta.imageSize = @(info.size); + debugMeta.codeFile = info.name; + + return debugMeta; +} + @end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryTracer.m b/Sources/Sentry/SentryTracer.m index d3d23364f4a..712e1490b7a 100644 --- a/Sources/Sentry/SentryTracer.m +++ b/Sources/Sentry/SentryTracer.m @@ -863,7 +863,7 @@ - (void)addAppStartMeasurements:(SentryTransaction *)transaction // The backend calculates statistics on the number and size of debug images for app // start transactions. Therefore, we add all debug images here. - transaction.debugMeta = [self.debugImageProvider getDebugImagesCrashed:NO]; + transaction.debugMeta = [self.debugImageProvider getDebugImagesFromCache]; } } } diff --git a/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h b/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h index e4278a5126c..d555c2ef1db 100644 --- a/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h +++ b/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h @@ -22,6 +22,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)stop; +- (NSArray *)getAllBinaryImages; + - (nullable SentryBinaryImageInfo *)imageByAddress:(const uint64_t)address; - (NSSet *)imagePathsForInAppInclude:(NSString *)inAppInclude; diff --git a/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h b/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h index b2b02963122..06a74235b11 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h +++ b/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h @@ -32,6 +32,9 @@ NS_ASSUME_NONNULL_BEGIN - (NSArray *)getDebugImagesForImageAddressesFromCache: (NSSet *)imageAddresses NS_SWIFT_NAME(getDebugImagesForImageAddressesFromCache(imageAddresses:)); + +- (NSArray *)getDebugImagesFromCache; + @end NS_ASSUME_NONNULL_END diff --git a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift index e65d235febb..2616e0a9eb7 100644 --- a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift +++ b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift @@ -47,6 +47,19 @@ class SentryProfileTestFixture { SentryDependencyContainer.sharedInstance().timerFactory = timeoutTimerFactory SentryDependencyContainer.sharedInstance().notificationCenterWrapper = notificationCenter + let image = DebugMeta() + image.name = "sentrytest" + image.imageAddress = "0x0000000105705000" + image.imageVmAddress = "0x0000000105705000" + image.codeFile = "codeFile" + image.debugID = "debugID" + image.imageSize = 100 + image.type = "macho" + + let debugImageProvider = TestDebugImageProvider() + debugImageProvider.debugImages = [image] + SentryDependencyContainer.sharedInstance().debugImageProvider = debugImageProvider + mockMetrics = MockMetric() systemWrapper.overrides.cpuUsage = mockMetrics.cpuUsage systemWrapper.overrides.memoryFootprintBytes = mockMetrics.memoryFootprint diff --git a/Tests/SentryTests/Helper/TestDebugImageProvider.swift b/Tests/SentryTests/Helper/TestDebugImageProvider.swift deleted file mode 100644 index 90d295d1b46..00000000000 --- a/Tests/SentryTests/Helper/TestDebugImageProvider.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation -import SentryTestUtils - -class TestDebugImageProvider: SentryDebugImageProvider { - var debugImages: [DebugMeta]? - - override func getDebugImages() -> [DebugMeta] { - getDebugImagesCrashed(true) - } - - override func getDebugImagesCrashed(_ isCrash: Bool) -> [DebugMeta] { - debugImages ?? super.getDebugImagesCrashed(isCrash) - } - - var getDebugImagesFromCacheForFramesInvocations = Invocations() - override func getDebugImagesFromCacheForFrames(frames: [Frame]) -> [DebugMeta] { - getDebugImagesFromCacheForFramesInvocations.record(Void()) - - return debugImages ?? super.getDebugImagesFromCacheForFrames(frames: frames) - } - - var getDebugImagesFromCacheForThreadsInvocations = Invocations() - override func getDebugImagesFromCacheForThreads(threads: [SentryThread]) -> [DebugMeta] { - getDebugImagesFromCacheForThreadsInvocations.record(Void()) - return debugImages ?? super.getDebugImagesFromCacheForThreads(threads: threads) - } -} diff --git a/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift b/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift index 63785d71cf9..091c4bc50bb 100644 --- a/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift +++ b/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift @@ -248,6 +248,19 @@ class PrivateSentrySDKOnlyTests: XCTestCase { * Smoke Tests profiling via PrivateSentrySDKOnly. Actual profiling unit tests are done elsewhere. */ func testProfilingStartAndCollect() throws { + let image = DebugMeta() + image.name = "sentrytest" + image.imageAddress = "0x0000000105705000" + image.imageVmAddress = "0x0000000105705000" + image.codeFile = "codeFile" + image.debugID = "debugID" + image.imageSize = 100 + image.type = "macho" + + let debugImageProvider = TestDebugImageProvider() + debugImageProvider.debugImages = [image] + SentryDependencyContainer.sharedInstance().debugImageProvider = debugImageProvider + if sentry_threadSanitizerIsPresent() { throw XCTSkip("Profiler does not run if thread sanitizer is attached.") } @@ -264,7 +277,19 @@ class PrivateSentrySDKOnlyTests: XCTestCase { let payload = PrivateSentrySDKOnly.collectProfileBetween(startTime, and: startTime + 200_000_000, forTrace: traceIdA) XCTAssertNotNil(payload) XCTAssertEqual(payload?["platform"] as? String, "cocoa") - XCTAssertNotNil(payload?["debug_meta"]) + + XCTAssertEqual(1, debugImageProvider.getDebugImagesFromCacheInvocations.count, "You must retrieve debug images from cache.") + let debugMeta = try XCTUnwrap(payload?["debug_meta"] as? [String: Any]) + let images = try XCTUnwrap(debugMeta["images"] as? [[String: Any]]) + let debugImage = try XCTUnwrap(images.first) + XCTAssertEqual(debugImage["name"] as? String, image.name) + XCTAssertEqual(debugImage["image_addr"] as? String, image.imageAddress) + XCTAssertEqual(debugImage["image_vmaddr"] as? String, image.imageVmAddress) + XCTAssertEqual(debugImage["code_file"] as? String, image.codeFile) + XCTAssertEqual(debugImage["debug_id"] as? String, image.debugID) + XCTAssertEqual(debugImage["image_size"] as? NSNumber, image.imageSize) + XCTAssertEqual(debugImage["type"] as? String, image.type) + XCTAssertNotNil(payload?["device"]) XCTAssertNotNil(payload?["profile_id"]) let profile = payload?["profile"] as? NSDictionary diff --git a/Tests/SentryTests/SentryBinaryImageCacheTests.swift b/Tests/SentryTests/SentryBinaryImageCacheTests.swift index 01f45da899b..65ddc4f3614 100644 --- a/Tests/SentryTests/SentryBinaryImageCacheTests.swift +++ b/Tests/SentryTests/SentryBinaryImageCacheTests.swift @@ -198,6 +198,34 @@ class SentryBinaryImageCacheTests: XCTestCase { self.sut.stop() self.sut.start() + + expectation.fulfill() + } + } + + waitForExpectations(timeout: 1) + } + + func testAddingImagesWhileGettingAllOnDifferentThread() { + let count = 1_000 + + let expectation = expectation(description: "Add images on background thread") + expectation.expectedFulfillmentCount = count + + self.sut.start() + + for i in 0.. Date: Fri, 15 Nov 2024 09:47:12 +0100 Subject: [PATCH 2/2] trigger testflight --- .github/workflows/testflight.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index fbc46498492..5c8fbe5423c 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -3,6 +3,7 @@ on: push: branches: - main + - impr/speed-up-get-debug-images-v2 paths: - 'Sources/**'