从 2.1 更新到 2.2 后 WCSession sendmessage 慢了一倍

WCSession sendmessage is twice as slow after updating from 2.1 to 2.2

我开发的 iOS 应用程序有一个与之配套的 Apple Watch 应用程序。我们最近开始收到关于 GPS 距离更新速度变慢并且手表比 phone 晚几秒的投诉。我一直在研究这个并写了一些测试代码,来自 [[WCSession defaultSession] sendMessage:message replyHandler:replyHandler errorHandler:errorHandler

的回复块

在 watchOS 2.2 中绝对比 2.1 慢两倍。我附上了下面的测试代码。

#pragma mark - Location Update.
/**
 * @description Provides an NSBlockOperation to be executed in an operation queue. This is an attempt to force serial
 * processing
 */
- (NSBlockOperation*)distanceUpdateBlock {
    NSBlockOperation *blockOp = [[NSBlockOperation alloc] init];
    __weak NSBlockOperation * weakOp = blockOp;
    __weak typeof(self) weakSelf = self;
    [blockOp addExecutionBlock:^{
        typeof(weakSelf) blockSafeSelf = weakSelf;
        typeof(weakOp) blockSafeOp = weakOp;

        if (!blockSafeOp.isCancelled) { // Make sure we haven't already been cancelled.
            __block NSDate *startDate = [NSDate date];
            __block BOOL completed = NO;
            void (^replyBlock)(NSDictionary*) =  ^(NSDictionary *message){
                if (!blockSafeOp.isCancelled) {
                    [blockSafeSelf processUserLocationOnWatch:message];

                    double replyTime = [[NSDate date] timeIntervalSinceDate:startDate];
                    NSLog(@"Reply Time: %.03f", replyTime);
                    completed = YES;
                }

            };
            void (^failBlock)(NSError*) =  ^(NSError *error) {
                if (!blockSafeOp.isCancelled) {
                    double replyTime = [[NSDate date] timeIntervalSinceDate:startDate];
                    NSLog(@"Reply Time Fail: %.03f", replyTime);
                    completed = YES;
                }
            };

            [self fetchUserLocationFromIphoneWithReplyHandler:replyBlock errorHandler:failBlock];
            do {
                usleep(10000); // 1/100th second wait to throttle evaluations (Don't worry - in final code I will subclass NSOperation and control when it actually finishes - this is for easy testing.)
            } while (!completed && !blockSafeOp.isCancelled && [blockSafeSelf isWatchReachable]); //(isWatchReachable just makes sure we have a session with the phone and it is reachable).
        }
    }];

    blockOp.completionBlock = ^{
        typeof(weakSelf) blockSafeSelf = weakSelf;
        typeof(weakOp) blockSafeOp = weakOp;
        if (!blockSafeOp.isCancelled) {
            [blockSafeSelf addOperationForLocationUpdate]; // since we are finished - add another operation.
        }
    };

    return blockOp;
}

- (void)addOperationForLocationUpdate {

    [distanceUpdateOperationQueue addOperation:[self distanceUpdateBlock]];
}

- (void)startUpdatingLocation {
    [self addOperationForLocationUpdate];
}

- (void)stopUpdatingLocation {
    [distanceUpdateOperationQueue cancelAllOperations];
}

- (void)fetchUserLocationFromIphoneWithReplyHandler:(nullable void (^)(NSDictionary<NSString *, id> *replyMessage))replyHandler errorHandler:(nullable void (^)(NSError *error))errorHandler {
    if (self.isSessionActive) {
        NSDictionary *message = @{kWatchSessionMessageTag:kWatchSessionMessageUserLocation};

        if (self.isWatchReachable) {
            [[WCSession defaultSession] sendMessage:message
                                       replyHandler:replyHandler
                                       errorHandler:errorHandler
             ];
        } else {
            errorHandler(nil);
        }

    } else {
        [self activateSession];
        errorHandler(nil);
    }
}

iPhone 端的处理程序简单地获取用户位置并使用编码信息调用 replyHandler。

2.2 上的时间日志看起来像(始终大约一秒)

回复时间:0.919

回复时间:0.952

回复时间:0.991

回复时间:0.981

回复时间:0.963

2.1 上的相同代码看起来像

回复时间:0.424

回复时间:0.421

回复时间:0.433

回复时间:0.419

此外,我注意到在 5 分钟(300 秒)后,错误处理程序开始在已经调用回复处理程序的消息上被调用。我看到另一个帖子有人也提到了这个,有没有其他人发生过这种情况并且知道为什么?

那么,Q1 - 有没有人 运行 遇到这种性能下降并想出如何使 replyHandler 运行 更快,或者找到更快的方法来获取更新?

Q2 - 5 分钟后调用 errorHandler 的解决方案。

只需消除几件事 - 我已尽职调查在接收消息和调用 replyHandler 之间测试 iOS 代码。 iOS 9.2/9.3 之间的处理时间没有变化。我已将范围缩小到这个电话。事实上,我们在以前的版本中这样做的方式现在是备份sendMessage 的operationQueue。所以现在我强制使用此测试代码一次调用一个。我们不再备份了,但是个人调用很慢。

所以,我今天 运行 测试了同一段代码,使用相同的设备,虽然代码没有改变,但现在 运行 是最初速度的两倍做了(在 2.1 中)。日志在 0.12 - 0.2 秒的范围内到达。从那时起唯一发生的事情就是软件更新。此外,5 分钟后不再调用失败块。所以这个问题的两个部分都神奇地起作用了。我目前使用的是 iOS 9.3.4(13G35),手表是 2.2.2。似乎是处理手表和 phone 之间的队列链中某个地方的 OS 问题。现在一切都很好。