Skip to content

Commit a2cf26e

Browse files
impr: Speed up getBinaryImages (#4435)
Add two new internal methods getDebugImagesFromCacheForFrames getDebugImagesFromCacheFrames to the SentryDebugImageProvider which use the significantly faster SentryBinaryImageCache. Fixes GH-4399
1 parent 9c84503 commit a2cf26e

21 files changed

+375
-35
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ via the option `swizzleClassNameExclude`.
2323

2424
- Serializing profile on a BG Thread (#4377) to avoid potentially slightly blocking the main thread.
2525
- Session Replay performance for SwiftUI (#4419)
26+
- Speed up getBinaryImages (#4435) for finishing transactions and capturing events
2627

2728
## 8.38.0-beta.1
2829

Sentry.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
624688192C048EF10006179C /* SentryBaggageSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 624688182C048EF10006179C /* SentryBaggageSerialization.swift */; };
9292
626E2D4C2BEA0C37005596FE /* SentryEnabledFeaturesBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626E2D4B2BEA0C37005596FE /* SentryEnabledFeaturesBuilderTests.swift */; };
9393
6271ADF32BA06D9B0098D2E9 /* SentryInternalSerializable.h in Headers */ = {isa = PBXBuildFile; fileRef = 6271ADF22BA06D9B0098D2E9 /* SentryInternalSerializable.h */; };
94+
6273513F2CBD14970021D100 /* SentryDebugImageProvider+HybridSDKs.h in Headers */ = {isa = PBXBuildFile; fileRef = 6273513E2CBD14970021D100 /* SentryDebugImageProvider+HybridSDKs.h */; };
9495
627E7589299F6FE40085504D /* SentryInternalDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 627E7588299F6FE40085504D /* SentryInternalDefines.h */; };
9596
62862B1C2B1DDBC8009B16E3 /* SentryDelayedFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 62862B1B2B1DDBC8009B16E3 /* SentryDelayedFrame.h */; };
9697
62862B1E2B1DDC35009B16E3 /* SentryDelayedFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 62862B1D2B1DDC35009B16E3 /* SentryDelayedFrame.m */; };
@@ -1081,6 +1082,7 @@
10811082
624688182C048EF10006179C /* SentryBaggageSerialization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBaggageSerialization.swift; sourceTree = "<group>"; };
10821083
626E2D4B2BEA0C37005596FE /* SentryEnabledFeaturesBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnabledFeaturesBuilderTests.swift; sourceTree = "<group>"; };
10831084
6271ADF22BA06D9B0098D2E9 /* SentryInternalSerializable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalSerializable.h; path = include/SentryInternalSerializable.h; sourceTree = "<group>"; };
1085+
6273513E2CBD14970021D100 /* SentryDebugImageProvider+HybridSDKs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryDebugImageProvider+HybridSDKs.h"; path = "include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h"; sourceTree = "<group>"; };
10841086
627E7588299F6FE40085504D /* SentryInternalDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalDefines.h; path = include/SentryInternalDefines.h; sourceTree = "<group>"; };
10851087
62862B1B2B1DDBC8009B16E3 /* SentryDelayedFrame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDelayedFrame.h; path = include/SentryDelayedFrame.h; sourceTree = "<group>"; };
10861088
62862B1D2B1DDC35009B16E3 /* SentryDelayedFrame.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDelayedFrame.m; sourceTree = "<group>"; };
@@ -2317,6 +2319,7 @@
23172319
7BA61CB8247BC57B00C130A8 /* SentryCrashDefaultBinaryImageProvider.h */,
23182320
7BA61CBA247BC5D800C130A8 /* SentryCrashDefaultBinaryImageProvider.m */,
23192321
7BA61CAA247BA98100C130A8 /* SentryDebugImageProvider.h */,
2322+
6273513E2CBD14970021D100 /* SentryDebugImageProvider+HybridSDKs.h */,
23202323
7BA61CAC247BAA0B00C130A8 /* SentryDebugImageProvider.m */,
23212324
7BA61CBE247CEA8100C130A8 /* SentryFormatter.h */,
23222325
7BA61CC7247D125400C130A8 /* SentryThreadInspector.h */,
@@ -4140,6 +4143,7 @@
41404143
7DC8310A2398283C0043DD9A /* SentryCrashIntegration.h in Headers */,
41414144
63FE718320DA4C1100CDBAE8 /* SentryCrashReportFixer.h in Headers */,
41424145
03F84D2027DD414C008FE43F /* SentryStackBounds.hpp in Headers */,
4146+
6273513F2CBD14970021D100 /* SentryDebugImageProvider+HybridSDKs.h in Headers */,
41434147
8E5D38E3261D4B57000D363D /* SentryPerformanceTrackingIntegration.h in Headers */,
41444148
63FE70F920DA4C1000CDBAE8 /* SentryCrashMonitor.h in Headers */,
41454149
D8BD2E6829361A0F00D96C6A /* PrivatesHeader.h in Headers */,

SentryTestUtils/TestClient.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ public class TestClient: SentryClient {
1616

1717
// Without this override we get a fatal error: use of unimplemented initializer
1818
// see https://stackoverflow.com/questions/28187261/ios-swift-fatal-error-use-of-unimplemented-initializer-init
19-
public override init(options: Options, transportAdapter: SentryTransportAdapter, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool, threadInspector: SentryThreadInspector, random: SentryRandomProtocol, locale: Locale, timezone: TimeZone) {
19+
public override init(options: Options, transportAdapter: SentryTransportAdapter, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool, threadInspector: SentryThreadInspector, debugImageProvider: SentryDebugImageProvider, random: SentryRandomProtocol, locale: Locale, timezone: TimeZone) {
2020
super.init(
2121
options: options,
2222
transportAdapter: transportAdapter,
2323
fileManager: fileManager,
2424
deleteOldEnvelopeItems: false,
2525
threadInspector: threadInspector,
26+
debugImageProvider: debugImageProvider,
2627
random: random,
2728
locale: locale,
2829
timezone: timezone

Sources/Sentry/SentryBinaryImageCache.m

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#import "SentryBinaryImageCache.h"
22
#import "SentryCrashBinaryImageCache.h"
3+
#include "SentryCrashUUIDConversion.h"
34
#import "SentryDependencyContainer.h"
45
#import "SentryInAppLogic.h"
56
#import "SentryLog.h"
@@ -59,7 +60,9 @@ - (void)binaryImageAdded:(const SentryCrashBinaryImage *)image
5960

6061
SentryBinaryImageInfo *newImage = [[SentryBinaryImageInfo alloc] init];
6162
newImage.name = imageName;
63+
newImage.UUID = [SentryBinaryImageCache convertUUID:image->uuid];
6264
newImage.address = image->address;
65+
newImage.vmAddress = image->vmAddress;
6366
newImage.size = image->size;
6467

6568
@synchronized(self) {
@@ -80,6 +83,17 @@ - (void)binaryImageAdded:(const SentryCrashBinaryImage *)image
8083
}
8184
}
8285

86+
+ (NSString *_Nullable)convertUUID:(const unsigned char *const)value
87+
{
88+
if (nil == value) {
89+
return nil;
90+
}
91+
92+
char uuidBuffer[37];
93+
sentrycrashdl_convertBinaryImageUUID(value, uuidBuffer);
94+
return [[NSString alloc] initWithCString:uuidBuffer encoding:NSASCIIStringEncoding];
95+
}
96+
8397
- (void)binaryImageRemoved:(const SentryCrashBinaryImage *)image
8498
{
8599
if (image == NULL) {

Sources/Sentry/SentryClient.m

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#import "SentryCrashDefaultMachineContextWrapper.h"
66
#import "SentryCrashIntegration.h"
77
#import "SentryCrashStackEntryMapper.h"
8-
#import "SentryDebugImageProvider.h"
8+
#import "SentryDebugImageProvider+HybridSDKs.h"
99
#import "SentryDependencyContainer.h"
1010
#import "SentryDispatchQueueWrapper.h"
1111
#import "SentryDsn.h"
@@ -128,6 +128,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options
128128
fileManager:fileManager
129129
deleteOldEnvelopeItems:deleteOldEnvelopeItems
130130
threadInspector:threadInspector
131+
debugImageProvider:[SentryDependencyContainer sharedInstance].debugImageProvider
131132
random:[SentryDependencyContainer sharedInstance].random
132133
locale:[NSLocale autoupdatingCurrentLocale]
133134
timezone:[NSCalendar autoupdatingCurrentCalendar].timeZone];
@@ -138,6 +139,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options
138139
fileManager:(SentryFileManager *)fileManager
139140
deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems
140141
threadInspector:(SentryThreadInspector *)threadInspector
142+
debugImageProvider:(SentryDebugImageProvider *)debugImageProvider
141143
random:(id<SentryRandom>)random
142144
locale:(NSLocale *)locale
143145
timezone:(NSTimeZone *)timezone
@@ -149,7 +151,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options
149151
self.fileManager = fileManager;
150152
self.threadInspector = threadInspector;
151153
self.random = random;
152-
self.debugImageProvider = [SentryDependencyContainer sharedInstance].debugImageProvider;
154+
self.debugImageProvider = debugImageProvider;
153155
self.locale = locale;
154156
self.timezone = timezone;
155157
self.attachmentProcessors = [[NSMutableArray alloc] init];
@@ -688,8 +690,8 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event
688690
BOOL debugMetaNotAttached = !(nil != event.debugMeta && event.debugMeta.count > 0);
689691
if (!isCrashEvent && shouldAttachStacktrace && debugMetaNotAttached
690692
&& event.threads != nil) {
691-
event.debugMeta = [self.debugImageProvider getDebugImagesForThreads:event.threads
692-
isCrash:NO];
693+
event.debugMeta =
694+
[self.debugImageProvider getDebugImagesFromCacheForThreads:event.threads];
693695
}
694696
}
695697

Sources/Sentry/SentryDebugImageProvider.m

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#import "SentryDebugImageProvider.h"
2+
#import "SentryBinaryImageCache.h"
23
#import "SentryCrashDefaultBinaryImageProvider.h"
34
#import "SentryCrashDynamicLinker.h"
45
#import "SentryCrashUUIDConversion.h"
56
#import "SentryDebugMeta.h"
7+
#import "SentryDependencyContainer.h"
68
#import "SentryFormatter.h"
79
#import "SentryFrame.h"
810
#import "SentryInternalDefines.h"
@@ -14,6 +16,8 @@
1416
@interface SentryDebugImageProvider ()
1517

1618
@property (nonatomic, strong) id<SentryCrashBinaryImageProvider> binaryImageProvider;
19+
@property (nonatomic, strong) SentryBinaryImageCache *binaryImageCache;
20+
1721
@end
1822

1923
@implementation SentryDebugImageProvider
@@ -23,16 +27,20 @@ - (instancetype)init
2327
SentryCrashDefaultBinaryImageProvider *provider =
2428
[[SentryCrashDefaultBinaryImageProvider alloc] init];
2529

26-
self = [self initWithBinaryImageProvider:provider];
30+
self = [self
31+
initWithBinaryImageProvider:provider
32+
binaryImageCache:SentryDependencyContainer.sharedInstance.binaryImageCache];
2733

2834
return self;
2935
}
3036

3137
/** Internal constructor for testing */
3238
- (instancetype)initWithBinaryImageProvider:(id<SentryCrashBinaryImageProvider>)binaryImageProvider
39+
binaryImageCache:(SentryBinaryImageCache *)binaryImageCache
3340
{
3441
if (self = [super init]) {
3542
self.binaryImageProvider = binaryImageProvider;
43+
self.binaryImageCache = binaryImageCache;
3644
}
3745
return self;
3846
}
@@ -95,6 +103,55 @@ - (void)extractDebugImageAddressFromFrames:(NSArray<SentryFrame *> *)frames
95103
return [self getDebugImagesForAddresses:imageAddresses isCrash:isCrash];
96104
}
97105

106+
- (NSArray<SentryDebugMeta *> *)getDebugImagesFromCacheForFrames:(NSArray<SentryFrame *> *)frames
107+
{
108+
NSMutableSet<NSString *> *imageAddresses = [[NSMutableSet alloc] init];
109+
[self extractDebugImageAddressFromFrames:frames intoSet:imageAddresses];
110+
111+
return [self getDebugImagesForImageAddressesFromCache:imageAddresses];
112+
}
113+
114+
- (NSArray<SentryDebugMeta *> *)getDebugImagesFromCacheForThreads:(NSArray<SentryThread *> *)threads
115+
{
116+
NSMutableSet<NSString *> *imageAddresses = [[NSMutableSet alloc] init];
117+
118+
for (SentryThread *thread in threads) {
119+
[self extractDebugImageAddressFromFrames:thread.stacktrace.frames intoSet:imageAddresses];
120+
}
121+
122+
return [self getDebugImagesForImageAddressesFromCache:imageAddresses];
123+
}
124+
125+
- (NSArray<SentryDebugMeta *> *)getDebugImagesForImageAddressesFromCache:
126+
(NSSet<NSString *> *)imageAddresses
127+
{
128+
NSMutableArray<SentryDebugMeta *> *result = [NSMutableArray array];
129+
130+
for (NSString *imageAddress in imageAddresses) {
131+
const uint64_t imageAddressAsUInt64 = sentry_UInt64ForHexAddress(imageAddress);
132+
SentryBinaryImageInfo *info = [self.binaryImageCache imageByAddress:imageAddressAsUInt64];
133+
if (info == nil) {
134+
continue;
135+
}
136+
137+
SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init];
138+
debugMeta.debugID = info.UUID;
139+
debugMeta.type = SentryDebugImageType;
140+
141+
if (info.vmAddress > 0) {
142+
debugMeta.imageVmAddress = sentry_formatHexAddressUInt64(info.vmAddress);
143+
}
144+
145+
debugMeta.imageAddress = sentry_formatHexAddressUInt64(info.address);
146+
debugMeta.imageSize = @(info.size);
147+
debugMeta.codeFile = info.name;
148+
149+
[result addObject:debugMeta];
150+
}
151+
152+
return result;
153+
}
154+
98155
- (NSArray<SentryDebugMeta *> *)getDebugImages
99156
{
100157
// maintains previous behavior for the same method call by also trying to gather crash info
@@ -118,7 +175,7 @@ - (void)extractDebugImageAddressFromFrames:(NSArray<SentryFrame *> *)frames
118175
- (SentryDebugMeta *)fillDebugMetaFrom:(SentryCrashBinaryImage)image
119176
{
120177
SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init];
121-
debugMeta.debugID = [SentryDebugImageProvider convertUUID:image.uuid];
178+
debugMeta.debugID = [SentryBinaryImageCache convertUUID:image.uuid];
122179
debugMeta.type = SentryDebugImageType;
123180

124181
if (image.vmAddress > 0) {
@@ -136,15 +193,4 @@ - (SentryDebugMeta *)fillDebugMetaFrom:(SentryCrashBinaryImage)image
136193
return debugMeta;
137194
}
138195

139-
+ (NSString *_Nullable)convertUUID:(const unsigned char *const)value
140-
{
141-
if (nil == value) {
142-
return nil;
143-
}
144-
145-
char uuidBuffer[37];
146-
sentrycrashdl_convertBinaryImageUUID(value, uuidBuffer);
147-
return [[NSString alloc] initWithCString:uuidBuffer encoding:NSASCIIStringEncoding];
148-
}
149-
150196
@end

Sources/Sentry/SentryDependencyContainer.m

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ - (instancetype)init
9393
_random = [[SentryRandom alloc] init];
9494
_threadWrapper = [[SentryThreadWrapper alloc] init];
9595
_binaryImageCache = [[SentryBinaryImageCache alloc] init];
96-
_debugImageProvider = [[SentryDebugImageProvider alloc] init];
9796
_dateProvider = [[SentryCurrentDateProvider alloc] init];
9897
}
9998
return self;
@@ -183,6 +182,16 @@ - (SentryThreadInspector *)threadInspector SENTRY_DISABLE_THREAD_SANITIZER(
183182
return _threadInspector;
184183
}
185184

185+
- (SentryDebugImageProvider *)debugImageProvider
186+
{
187+
@synchronized(sentryDependencyContainerLock) {
188+
if (_debugImageProvider == nil) {
189+
_debugImageProvider = [[SentryDebugImageProvider alloc] init];
190+
}
191+
return _debugImageProvider;
192+
}
193+
}
194+
186195
- (SentryExtraContextProvider *)extraContextProvider SENTRY_DISABLE_THREAD_SANITIZER(
187196
"double-checked lock produce false alarms")
188197
{

Sources/Sentry/SentryThreadInspector.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#import "SentryThreadInspector.h"
2-
#import "SentryBinaryImageCache.h"
32
#import "SentryCrashDefaultMachineContextWrapper.h"
43
#import "SentryCrashStackCursor.h"
54
#include "SentryCrashStackCursor_MachineContext.h"

Sources/Sentry/SentryTracer.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#import "PrivateSentrySDKOnly.h"
22
#import "SentryClient.h"
3-
#import "SentryDebugImageProvider.h"
3+
#import "SentryDebugImageProvider+HybridSDKs.h"
44
#import "SentryDependencyContainer.h"
55
#import "SentryEvent+Private.h"
66
#import "SentryFileManager.h"
@@ -717,8 +717,8 @@ - (SentryTransaction *)toTransaction
717717
if (framesOfAllSpans.count > 0) {
718718
SentryDebugImageProvider *debugImageProvider
719719
= SentryDependencyContainer.sharedInstance.debugImageProvider;
720-
transaction.debugMeta = [debugImageProvider getDebugImagesForFrames:framesOfAllSpans
721-
isCrash:NO];
720+
transaction.debugMeta =
721+
[debugImageProvider getDebugImagesFromCacheForFrames:framesOfAllSpans];
722722
}
723723

724724
#if SENTRY_HAS_UIKIT

Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ NS_ASSUME_NONNULL_BEGIN
44

55
@interface SentryBinaryImageInfo : NSObject
66
@property (nonatomic, strong) NSString *name;
7+
@property (nonatomic, copy) NSString *UUID;
8+
@property (nonatomic) uint64_t vmAddress;
79
@property (nonatomic) uint64_t address;
810
@property (nonatomic) uint64_t size;
11+
912
@end
1013

1114
/**
@@ -23,6 +26,8 @@ NS_ASSUME_NONNULL_BEGIN
2326

2427
- (nullable NSString *)pathForInAppInclude:(NSString *)inAppInclude;
2528

29+
+ (NSString *_Nullable)convertUUID:(const unsigned char *const)value;
30+
2631
@end
2732

2833
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)