Skip to content

Commit

Permalink
[ASTextKitRenderer] Adding locking when accessing the text renderer c…
Browse files Browse the repository at this point in the history
…ache (#2075)

While NSCache is thread safe, that alone does not make `rendererForAttributes` thread safe. This experiment will add a lock to `rendererForAttributes` to see how that affects performance/stability. As second experiment will forego the cache altogether to validate that we are getting some value out of having a renderer cache.
  • Loading branch information
rcancro committed Jan 25, 2023
1 parent c989e1a commit 2c7ba22
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 2 deletions.
2 changes: 2 additions & 0 deletions Source/ASExperimentalFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ typedef NS_OPTIONS(NSUInteger, ASExperimentalFeatures) {
ASExperimentalDisableGlobalTextkitLock = 1 << 10, // exp_disable_global_textkit_lock
ASExperimentalMainThreadOnlyDataController = 1 << 11, // exp_main_thread_only_data_controller
ASExperimentalRangeUpdateOnChangesetUpdate = 1 << 12, // exp_range_update_on_changeset_update
ASExperimentalNoTextRendererCache = 1 << 13, // exp_no_text_renderer_cache
ASExperimentalLockTextRendererCache = 1 << 14, // exp_lock_text_renderer_cache
ASExperimentalFeatureAll = 0xFFFFFFFF
};

Expand Down
5 changes: 4 additions & 1 deletion Source/ASExperimentalFeatures.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
@"exp_optimize_data_controller_pipeline",
@"exp_disable_global_textkit_lock",
@"exp_main_thread_only_data_controller",
@"exp_range_update_on_changeset_update"]));
@"exp_range_update_on_changeset_update",
@"exp_no_text_renderer_cache",
@"exp_lock_text_renderer_cache"]));

if (flags == ASExperimentalFeatureAll) {
return allNames;
}
Expand Down
19 changes: 18 additions & 1 deletion Source/ASTextNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ - (BOOL)isEqual:(ASTextNodeRendererKey *)object
we maintain a LRU renderer cache that is queried via a unique key based on text kit attributes and constrained size.
*/

static ASTextKitRenderer *rendererForAttributes(ASTextKitAttributes attributes, CGSize constrainedSize)
static ASTextKitRenderer *_rendererForAttributes(ASTextKitAttributes attributes, CGSize constrainedSize)
{
NSCache *cache = sharedRendererCache();

Expand All @@ -130,6 +130,23 @@ - (BOOL)isEqual:(ASTextNodeRendererKey *)object
return renderer;
}

static AS::RecursiveMutex __sharedRendererCacheInstanceLock__;

static ASTextKitRenderer *rendererForAttributes(ASTextKitAttributes attributes, CGSize constrainedSize)
{
BOOL neverCache = ASActivateExperimentalFeature(ASExperimentalNoTextRendererCache);
if (neverCache) {
return [[ASTextKitRenderer alloc] initWithTextKitAttributes:attributes constrainedSize:constrainedSize];
}

BOOL lockCache = ASActivateExperimentalFeature(ASExperimentalLockTextRendererCache);
if (lockCache) {
AS::MutexLocker l(__sharedRendererCacheInstanceLock__);
return _rendererForAttributes(attributes, constrainedSize);
}
return _rendererForAttributes(attributes, constrainedSize);
}

#pragma mark - ASTextNodeDrawParameter

@interface ASTextNodeDrawParameter : NSObject {
Expand Down

0 comments on commit 2c7ba22

Please sign in to comment.