-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Darwin] MTRDevice should throttle writes to the attribute storage #33535
Changes from all commits
4975c92
c8ed181
c67825f
309852d
3f2b72d
683e48b
d8f14fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/** | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <Matter/MTRDefines.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
/** | ||
* Class that configures how MTRDevice objects persist its attributes to storage, so as to not | ||
* overwhelm the underlying storage system. | ||
*/ | ||
MTR_NEWLY_AVAILABLE | ||
@interface MTRDeviceStorageBehaviorConfiguration : NSObject <NSCopying> | ||
|
||
/** | ||
* Create configuration with a default set of values. See description below for details. | ||
*/ | ||
+ (instancetype)configurationWithDefaultStorageBehavior; | ||
|
||
/** | ||
* Create configuration that disables storage behavior optimizations. | ||
*/ | ||
+ (instancetype)configurationWithStorageBehaviorOptimizationDisabled; | ||
|
||
/** | ||
* Create configuration with specified values. See description below for details, and the list of | ||
* properties below for valid ranges of these values. | ||
*/ | ||
+ (instancetype)configurationWithReportToPersistenceDelayTime:(NSTimeInterval)reportToPersistenceDelayTime | ||
reportToPersistenceDelayTimeMax:(NSTimeInterval)reportToPersistenceDelayTimeMax | ||
recentReportTimesMaxCount:(NSUInteger)recentReportTimesMaxCount | ||
timeBetweenReportsTooShortThreshold:(NSTimeInterval)timeBetweenReportsTooShortThreshold | ||
timeBetweenReportsTooShortMinThreshold:(NSTimeInterval)timeBetweenReportsTooShortMinThreshold | ||
reportToPersistenceDelayMaxMultiplier:(double)reportToPersistenceDelayMaxMultiplier | ||
deviceReportingExcessivelyIntervalThreshold:(NSTimeInterval)deviceReportingExcessivelyIntervalThreshold; | ||
|
||
/** | ||
* Storage behavior with values in the allowed range: | ||
* | ||
* Each time a report comes in, MTRDevice will wait reportToPersistDelayTime before persisting the | ||
* changes to storage. If another report comes in during this internal, MTRDevice will wait another | ||
* reportToPersistDelayTime interval, until reportToPersistDelayTimeMax is reached, at which | ||
* point all the changes so far will be written to storage. | ||
* | ||
* MTRDevice will also track recentReportTimesMaxCount number of report times. If the running | ||
* average time between reports dips below timeBetweenReportsTooShortThreshold, a portion of the | ||
* reportToPersistenceDelayMaxMultiplier will be applied to both the reportToPersistenceDelayTime | ||
* and reportToPersistenceDelayTimeMax. The multiplier will reach the max when the average time | ||
* between reports reach timeBetweenReportsTooShortMinThreshold. | ||
* | ||
* When the running average time between reports dips below timeBetweenReportsTooShortMinThreshold | ||
* for the first time, the time will be noted. If the device remains in this state for longer than | ||
* deviceReportingExcessivelyIntervalThreshold, persistence will stop until the average time between | ||
* reports go back above timeBetweenReportsTooShortMinThreshold. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "goes back". In terms of the implementation, if the device is reporting excessively for a bit, and then stops reporting entirely for a long time, shouldn't we persist at some point? Right now, I don't think we do.... Seems to me like we should compute when the average time would go back above if we got no reports until then and schedule something to persist at that point or something. |
||
*/ | ||
|
||
/** | ||
* If disableStorageBehaviorOptimization is set to YES, then all the waiting mechanism as described above | ||
* is disabled. | ||
*/ | ||
@property (nonatomic, assign) BOOL disableStorageBehaviorOptimization; | ||
|
||
/** | ||
* If any of these properties are set to be out of the documented limits, these default values will | ||
* be used to replace all of them: | ||
* | ||
* reportToPersistenceDelayTimeDefault (15) | ||
* reportToPersistenceDelayTimeMaxDefault (20 * kReportToPersistenceDelayTimeDefault) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kReportToPersistenceDelayTimeDefault is not a concept in this API... Should just say |
||
* recentReportTimesMaxCountDefault (12) | ||
* timeBetweenReportsTooShortThresholdDefault (15) | ||
* timeBetweenReportsTooShortMinThresholdDefault (5) | ||
* reportToPersistenceDelayMaxMultiplierDefault (10) | ||
* deviceReportingExcessivelyIntervalThresholdDefault (5 * 60) | ||
*/ | ||
@property (nonatomic, assign) NSTimeInterval reportToPersistenceDelayTime; /* must be > 0 */ | ||
@property (nonatomic, assign) NSTimeInterval reportToPersistenceDelayTimeMax; /* must be larger than reportToPersistenceDelayTime */ | ||
@property (nonatomic, assign) NSUInteger recentReportTimesMaxCount; /* must be >= 2 */ | ||
@property (nonatomic, assign) NSTimeInterval timeBetweenReportsTooShortThreshold; /* must be > 0 */ | ||
@property (nonatomic, assign) NSTimeInterval timeBetweenReportsTooShortMinThreshold; /* must be > 0 and smaller than timeBetweenReportsTooShortThreshold */ | ||
@property (nonatomic, assign) double reportToPersistenceDelayMaxMultiplier; /* must be > 1 */ | ||
@property (nonatomic, assign) NSTimeInterval deviceReportingExcessivelyIntervalThreshold; /* must be > 0 */ | ||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/** | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#import "MTRDeviceStorageBehaviorConfiguration.h" | ||
|
||
#import "MTRLogging_Internal.h" | ||
|
||
#define kReportToPersistenceDelayTimeDefault (15) | ||
#define kReportToPersistenceDelayTimeMaxDefault (20 * kReportToPersistenceDelayTimeDefault) | ||
#define kRecentReportTimesMaxCountDefault (12) | ||
#define kTimeBetweenReportsTooShortThresholdDefault (15) | ||
#define kTimeBetweenReportsTooShortMinThresholdDefault (5) | ||
#define kReportToPersistenceDelayMaxMultiplierDefault (10) | ||
#define kDeviceReportingExcessivelyIntervalThresholdDefault (5 * 60) | ||
|
||
@implementation MTRDeviceStorageBehaviorConfiguration | ||
|
||
+ (instancetype)configurationWithReportToPersistenceDelayTime:(NSTimeInterval)reportToPersistenceDelayTime | ||
reportToPersistenceDelayTimeMax:(NSTimeInterval)reportToPersistenceDelayTimeMax | ||
recentReportTimesMaxCount:(NSUInteger)recentReportTimesMaxCount | ||
timeBetweenReportsTooShortThreshold:(NSTimeInterval)timeBetweenReportsTooShortThreshold | ||
timeBetweenReportsTooShortMinThreshold:(NSTimeInterval)timeBetweenReportsTooShortMinThreshold | ||
reportToPersistenceDelayMaxMultiplier:(double)reportToPersistenceDelayMaxMultiplier | ||
deviceReportingExcessivelyIntervalThreshold:(NSTimeInterval)deviceReportingExcessivelyIntervalThreshold | ||
{ | ||
auto newConfiguration = [[MTRDeviceStorageBehaviorConfiguration alloc] init]; | ||
newConfiguration.reportToPersistenceDelayTime = reportToPersistenceDelayTime; | ||
newConfiguration.reportToPersistenceDelayTimeMax = reportToPersistenceDelayTimeMax; | ||
newConfiguration.recentReportTimesMaxCount = recentReportTimesMaxCount; | ||
newConfiguration.timeBetweenReportsTooShortThreshold = timeBetweenReportsTooShortThreshold; | ||
newConfiguration.timeBetweenReportsTooShortMinThreshold = timeBetweenReportsTooShortMinThreshold; | ||
newConfiguration.reportToPersistenceDelayMaxMultiplier = reportToPersistenceDelayMaxMultiplier; | ||
newConfiguration.deviceReportingExcessivelyIntervalThreshold = deviceReportingExcessivelyIntervalThreshold; | ||
|
||
return newConfiguration; | ||
} | ||
|
||
+ (instancetype)configurationWithDefaultStorageBehavior | ||
{ | ||
auto newConfiguration = [[MTRDeviceStorageBehaviorConfiguration alloc] init]; | ||
[newConfiguration checkValuesAndResetToDefaultIfNecessary]; | ||
return newConfiguration; | ||
} | ||
|
||
+ (instancetype)configurationWithStorageBehaviorOptimizationDisabled | ||
{ | ||
auto newConfiguration = [[MTRDeviceStorageBehaviorConfiguration alloc] init]; | ||
newConfiguration.disableStorageBehaviorOptimization = YES; | ||
return newConfiguration; | ||
} | ||
|
||
- (NSString *)description | ||
{ | ||
return [NSString stringWithFormat:@"<MTRDeviceStorageBehaviorConfiguration(%p): disabled %s reportToPersistenceDelayTime %lf reportToPersistenceDelayTimeMax %lf recentReportTimesMaxCount %lu timeBetweenReportsTooShortThreshold %lf timeBetweenReportsTooShortMinThreshold %lf reportToPersistenceDelayMaxMultiplier %lf deviceReportingExcessivelyIntervalThreshold %lf", self, _disableStorageBehaviorOptimization ? "YES" : "NO", _reportToPersistenceDelayTime, _reportToPersistenceDelayTimeMax, static_cast<unsigned long>(_recentReportTimesMaxCount), _timeBetweenReportsTooShortThreshold, _timeBetweenReportsTooShortMinThreshold, _reportToPersistenceDelayMaxMultiplier, _deviceReportingExcessivelyIntervalThreshold]; | ||
} | ||
|
||
- (void)checkValuesAndResetToDefaultIfNecessary | ||
{ | ||
if (_disableStorageBehaviorOptimization) { | ||
return; | ||
} | ||
|
||
// Sanity check all the values, and if any is out of range, reset to default values | ||
if ((_reportToPersistenceDelayTime <= 0) || (_reportToPersistenceDelayTimeMax <= 0) || (_reportToPersistenceDelayTimeMax < _reportToPersistenceDelayTime) || (_recentReportTimesMaxCount < 2) || (_timeBetweenReportsTooShortThreshold <= 0) || (_timeBetweenReportsTooShortMinThreshold <= 0) || (_timeBetweenReportsTooShortMinThreshold > _timeBetweenReportsTooShortThreshold) || (_reportToPersistenceDelayMaxMultiplier <= 1) || (_deviceReportingExcessivelyIntervalThreshold <= 0)) { | ||
MTR_LOG_ERROR("%@ storage behavior: MTRDeviceStorageBehaviorConfiguration values out of bounds - resetting to default", self); | ||
|
||
_reportToPersistenceDelayTime = kReportToPersistenceDelayTimeDefault; | ||
_reportToPersistenceDelayTimeMax = kReportToPersistenceDelayTimeMaxDefault; | ||
_recentReportTimesMaxCount = kRecentReportTimesMaxCountDefault; | ||
_timeBetweenReportsTooShortThreshold = kTimeBetweenReportsTooShortThresholdDefault; | ||
_timeBetweenReportsTooShortMinThreshold = kTimeBetweenReportsTooShortMinThresholdDefault; | ||
_reportToPersistenceDelayMaxMultiplier = kReportToPersistenceDelayMaxMultiplierDefault; | ||
_deviceReportingExcessivelyIntervalThreshold = kDeviceReportingExcessivelyIntervalThresholdDefault; | ||
} | ||
} | ||
|
||
- (id)copyWithZone:(NSZone *)zone | ||
{ | ||
auto newConfiguration = [[MTRDeviceStorageBehaviorConfiguration alloc] init]; | ||
newConfiguration.disableStorageBehaviorOptimization = _disableStorageBehaviorOptimization; | ||
newConfiguration.reportToPersistenceDelayTime = _reportToPersistenceDelayTime; | ||
newConfiguration.reportToPersistenceDelayTimeMax = _reportToPersistenceDelayTimeMax; | ||
newConfiguration.recentReportTimesMaxCount = _recentReportTimesMaxCount; | ||
newConfiguration.timeBetweenReportsTooShortThreshold = _timeBetweenReportsTooShortThreshold; | ||
newConfiguration.timeBetweenReportsTooShortMinThreshold = _timeBetweenReportsTooShortMinThreshold; | ||
newConfiguration.reportToPersistenceDelayMaxMultiplier = _reportToPersistenceDelayMaxMultiplier; | ||
newConfiguration.deviceReportingExcessivelyIntervalThreshold = _deviceReportingExcessivelyIntervalThreshold; | ||
|
||
return newConfiguration; | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Copyright (c) 2024 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#import "MTRDeviceStorageBehaviorConfiguration.h" | ||
|
||
@interface MTRDeviceStorageBehaviorConfiguration () | ||
- (void)checkValuesAndResetToDefaultIfNecessary; | ||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"their" not "its", since it's "objects"?