Skip to content

Commit 3ca0e64

Browse files
metascroyfacebook-github-bot
authored andcommitted
Back out "Improve asset management"
Summary: Original commit changeset: 46d2f763787b Original Phabricator Diff: D80715432 Since the introduction of D80715432, WhatsApp is seeing an increase in model load failures with error code 0x23 (P1948468840). From logs, the underlying issue is something like "Model init failed “model.mlmodelc” couldn’t be moved to “models” because an item with the same name already exists." FB app has also seen an increase in error code 0x23 since 9/5. We are unable to reproduce this error locally, but out of caution we want to revert D80715432 and see if the errors resolve. Since D80715432 landed, we also landed D81256207 to add more logging. To prevent conflicts, we backout in 3 steps: * In diff 1/3, we backout D81256207, which added more logging * In diff 2/3, we backout D80715432, which is the problematic diff we're trying to revert * In diff 3/3, we introduce some of the logging we backed out in diff 1/3 Differential Revision: D82581443
1 parent 75cb986 commit 3ca0e64

File tree

4 files changed

+127
-215
lines changed

4 files changed

+127
-215
lines changed

backends/apple/coreml/runtime/delegate/ETCoreMLAssetManager.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,6 @@ NS_ASSUME_NONNULL_BEGIN
9999
- (NSUInteger)compact:(NSUInteger)sizeInBytes error:(NSError* __autoreleasing*)error;
100100

101101

102-
/// Executes a block with a unique temporary directory.
103-
///
104-
/// A new temporary subdirectory URL is created inside the receiver’s designated
105-
/// base directory. The directory is passed to the block, which can use it to
106-
/// perform temporary file operations. After the block finishes executing,
107-
/// the directory and its contents are removed.
108-
///
109-
/// @param block A block to execute. The block receives a unique URL.
110-
- (void)withTemporaryDirectory:(void (^)(NSURL* directoryURL))block;
111-
112-
113102
/// Purges the assets storage. The assets are moved to the trash directory and are asynchronously
114103
/// deleted.
115104
///
@@ -128,12 +117,6 @@ NS_ASSUME_NONNULL_BEGIN
128117
/// contents are deleted asynchronously.
129118
@property (copy, readonly, nonatomic) NSURL* trashDirectoryURL;
130119

131-
132-
/// The staging directory URL, used to hold assets that are being prepared or processed
133-
/// before they are moved into their final location. The contents of this directory
134-
/// are temporary and may be cleared when no longer needed.
135-
@property (copy, readonly, nonatomic) NSURL* stagingDirectoryURL;
136-
137120
/// The file manager.
138121
@property (strong, readonly, nonatomic) NSFileManager* fileManager;
139122

backends/apple/coreml/runtime/delegate/ETCoreMLAssetManager.mm

Lines changed: 38 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -254,29 +254,6 @@ BOOL is_asset_alive(NSMapTable<NSString *, ETCoreMLAsset *> *assets_in_use_map,
254254

255255
return assets;
256256
}
257-
258-
NSURL * _Nullable move_to_directory(NSURL *url,
259-
NSURL *directoryURL,
260-
NSFileManager *fileManager,
261-
NSError * __autoreleasing *error) {
262-
if (!url) {
263-
ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorInternalError, "Move operation failed: source URL is nil.");
264-
return nil;
265-
}
266-
267-
if (!directoryURL) {
268-
ETCoreMLLogErrorAndSetNSError(error, ETCoreMLErrorInternalError, "Move operation failed: destination URL is nil.");
269-
return nil;
270-
}
271-
272-
NSURL *dstURL = [directoryURL URLByAppendingPathComponent:[NSUUID UUID].UUIDString];
273-
if (![fileManager moveItemAtURL:url toURL:dstURL error:error]) {
274-
return nil;
275-
}
276-
277-
return dstURL;
278-
}
279-
280257
} //namespace
281258

282259
@interface ETCoreMLAssetManager () <NSFileManagerDelegate> {
@@ -322,17 +299,12 @@ - (nullable instancetype)initWithDatabase:(const std::shared_ptr<Database>&)data
322299
if (!managedAssetsDirectoryURL) {
323300
return nil;
324301
}
325-
302+
326303
NSURL *managedTrashDirectoryURL = ::create_directory_if_needed(trashDirectoryURL, @"models", fileManager, error);
327304
if (!managedTrashDirectoryURL) {
328305
return nil;
329306
}
330-
331-
NSURL *managedStagingDirectoryURL = ::create_directory_if_needed(assetsDirectoryURL, @"staging", fileManager, error);
332-
if (!managedStagingDirectoryURL) {
333-
return nil;
334-
}
335-
307+
336308
// If directory is empty then purge the stores
337309
if (::is_directory_empty(managedAssetsDirectoryURL, fileManager, nil)) {
338310
assetsMetaStore.impl()->purge(ec);
@@ -343,7 +315,6 @@ - (nullable instancetype)initWithDatabase:(const std::shared_ptr<Database>&)data
343315
_assetsStore = std::move(assetsStore);
344316
_assetsMetaStore = std::move(assetsMetaStore);
345317
_assetsDirectoryURL = managedAssetsDirectoryURL;
346-
_stagingDirectoryURL = managedStagingDirectoryURL;
347318
_trashDirectoryURL = managedTrashDirectoryURL;
348319
_estimatedSizeInBytes = sizeInBytes.value();
349320
_maxAssetsSizeInBytes = maxAssetsSizeInBytes;
@@ -375,15 +346,15 @@ - (nullable instancetype)initWithDatabaseURL:(NSURL *)databaseURL
375346
error:error];
376347
}
377348

378-
- (void)withTemporaryDirectory:(void (^)(NSURL *directoryURL))block {
379-
NSURL *dstURL = [self.stagingDirectoryURL URLByAppendingPathComponent:[NSUUID UUID].UUIDString];
380-
block(dstURL);
381-
if (![self.fileManager fileExistsAtPath:dstURL.path]) {
382-
return;
349+
- (nullable NSURL *)moveURL:(NSURL *)url
350+
toUniqueURLInDirectory:(NSURL *)directoryURL
351+
error:(NSError * __autoreleasing *)error {
352+
NSURL *dstURL = [directoryURL URLByAppendingPathComponent:[NSUUID UUID].UUIDString];
353+
if (![self.fileManager moveItemAtURL:url toURL:dstURL error:error]) {
354+
return nil;
383355
}
384-
385-
move_to_directory(dstURL, self.trashDirectoryURL, self.fileManager, nil);
386-
[self cleanupTrashDirectory];
356+
357+
return dstURL;
387358
}
388359

389360
- (void)cleanupAssetIfNeeded:(ETCoreMLAsset *)asset {
@@ -436,8 +407,9 @@ - (nullable ETCoreMLAsset *)_storeAssetAtURL:(NSURL *)srcURL
436407
return false;
437408
}
438409

439-
// If a file already exists at `dstURL`, move it to the trash for removal.
440-
move_to_directory(dstURL, self.trashDirectoryURL, self.fileManager, nil);
410+
// If an asset exists move it
411+
[self moveURL:dstURL toUniqueURLInDirectory:self.trashDirectoryURL error:nil];
412+
441413
// Move the asset to assets directory.
442414
if (![self.fileManager moveItemAtURL:srcURL toURL:dstURL error:error]) {
443415
return false;
@@ -461,25 +433,16 @@ - (nullable ETCoreMLAsset *)_storeAssetAtURL:(NSURL *)srcURL
461433
}
462434

463435
- (void)triggerCompaction {
464-
if (self.estimatedSizeInBytes >= self.maxAssetsSizeInBytes) {
465-
__weak __typeof(self) weakSelf = self;
466-
dispatch_async(self.syncQueue, ^{
467-
NSError *localError = nil;
468-
if (![weakSelf _compact:self.maxAssetsSizeInBytes error:&localError]) {
469-
ETCoreMLLogError(localError, "Failed to compact asset store.");
470-
}
471-
});
436+
if (self.estimatedSizeInBytes < self.maxAssetsSizeInBytes) {
437+
return;
472438
}
473-
474-
// Always clean the trash directory to ensure a minimal footprint.
475-
// The `trashQueue` is serialized, so only one cleanup will run at a time.
476-
[self cleanupTrashDirectory];
477-
}
478-
479-
- (void)cleanupTrashDirectory {
439+
480440
__weak __typeof(self) weakSelf = self;
481-
dispatch_async(self.trashQueue, ^{
482-
[weakSelf removeFilesInTrashDirectory];
441+
dispatch_async(self.syncQueue, ^{
442+
NSError *localError = nil;
443+
if (![weakSelf _compact:self.maxAssetsSizeInBytes error:&localError]) {
444+
ETCoreMLLogError(localError, "Failed to compact asset store.");
445+
}
483446
});
484447
}
485448

@@ -585,7 +548,7 @@ - (BOOL)_removeAssetWithIdentifier:(NSString *)identifier
585548

586549
NSURL *assetURL = ::get_asset_url(assetValue);
587550
if ([self.fileManager fileExistsAtPath:assetURL.path] &&
588-
!move_to_directory(assetURL, self.trashDirectoryURL, self.fileManager, error)) {
551+
![self moveURL:assetURL toUniqueURLInDirectory:self.trashDirectoryURL error:error]) {
589552
return false;
590553
}
591554

@@ -686,7 +649,13 @@ - (NSUInteger)_compact:(NSUInteger)sizeInBytes error:(NSError * __autoreleasing
686649
identifier);
687650
}
688651
}
689-
652+
653+
// Trigger cleanup.
654+
__weak __typeof(self) weakSelf = self;
655+
dispatch_async(self.trashQueue, ^{
656+
[weakSelf removeFilesInTrashDirectory];
657+
});
658+
690659
return _estimatedSizeInBytes;
691660
}
692661

@@ -695,10 +664,7 @@ - (NSUInteger)compact:(NSUInteger)sizeInBytes error:(NSError * __autoreleasing *
695664
dispatch_sync(self.syncQueue, ^{
696665
result = [self _compact:sizeInBytes error:error];
697666
});
698-
699-
// Always clean the trash directory to ensure a minimal footprint.
700-
// The `trashQueue` is serialized, so only one cleanup will run at a time.
701-
[self cleanupTrashDirectory];
667+
702668
return result;
703669
}
704670

@@ -742,7 +708,7 @@ - (BOOL)_purge:(NSError * __autoreleasing *)error {
742708
}
743709

744710
// Move the the whole assets directory to the temp directory.
745-
if (!move_to_directory(self.assetsDirectoryURL, self.trashDirectoryURL, self.fileManager, error)) {
711+
if (![self moveURL:self.assetsDirectoryURL toUniqueURLInDirectory:self.trashDirectoryURL error:error]) {
746712
return false;
747713
}
748714

@@ -758,7 +724,13 @@ - (BOOL)_purge:(NSError * __autoreleasing *)error {
758724

759725
::set_error_from_error_code(ec, error);
760726
// Trigger cleanup
761-
[self cleanupTrashDirectory];
727+
if (status) {
728+
__weak __typeof(self) weakSelf = self;
729+
dispatch_async(self.trashQueue, ^{
730+
[weakSelf removeFilesInTrashDirectory];
731+
});
732+
}
733+
762734
return static_cast<BOOL>(status);
763735
}
764736

backends/apple/coreml/runtime/delegate/ETCoreMLModelLoader.mm

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,21 @@ + (nullable ETCoreMLModel *)loadModelWithContentsOfURL:(NSURL *)compiledModelURL
6262
if (model) {
6363
return model;
6464
}
65-
66-
if (error) {
67-
*error = localError;
65+
66+
if (localError) {
67+
ETCoreMLLogError(localError,
68+
"Failed to load model from compiled asset with identifier = %@",
69+
identifier);
6870
}
69-
70-
return nil;
71+
72+
// If store failed then we will load the model from compiledURL.
73+
auto backingAsset = Asset::make(compiledModelURL, identifier, assetManager.fileManager, error);
74+
if (!backingAsset) {
75+
return nil;
76+
}
77+
78+
asset = [[ETCoreMLAsset alloc] initWithBackingAsset:backingAsset.value()];
79+
return ::get_model_from_asset(asset, configuration, metadata, error);
7180
}
7281

7382
@end

0 commit comments

Comments
 (0)