簡體   English   中英

iOS CPU使用率飆升

[英]iOS CPU usage skyrockets here

我的應用存在問題,在收集數據時,它的CPU使用率會飆升至100%以上。 我已經盡我所能在處理中發揮作用,以使它不會鎖定設備,並且仍然繼續獲取所需的數據。

我們的客戶有一些大型數據庫,因此下載整個數據庫是不可能的。 我們還使用REMObjects作為中間件,因此我必須使用它。 我所做的就是弄清楚用戶需要什么數據,並設置了一系列調用來收集該信息。 我認為我的問題出在哪里,因為數據庫在一個呼叫中最多只能處理1500個項目。

這是發送到服務器的示例查詢字符串。

SELECT COMMUNICATIONID, PHONEEXTENTION, PHONEDESC, PHONETIMETOCALL, PHONENUMBER 
FROM PHONE WHERE COMMUNICATIONID IN (3761, 3793, 5530, 4957, 4320, 1914, 3715, 6199, 5548,
5580, 5994, 5867, 1437, 4943, 6217, 3765, 2442, 227, 4084, 977, 6822, 5680, 263, 4502, 
327, 6112, 136, 7053, 5571, 6958, 6799, 5525, 6530, 4779, 604, 2182, 6198, 3792, 6071, 
4383, 5866, 7444, 1309, 226, 4083, 5916, 1295, 626, 1249, 1950, 2141, 3369, 326, 135, 
6780, 5411, 5938, 4424, 6034, 649, 6179, 5861, 4778, 5479, 2181, 6197, 3791, 5815, 6070, 
6420, 7935, 4542, 4319, 6679, 4942, 4082, 4974, 5533, 5788, 5597, 976, 3764, 1917, 6202, 
134, 6779, 3768, 5410, 5665, 7880, 7052, 6033, 5492, 6815, 3118, 4218, 5110, 6529, 6115, 
6069, 348, 4318, 4382, 1498, 6406, 4941, 7443, 2376, 4623, 5755, 5532, 6201, 6392, 625, 
7270, 4977, 6396, 6524, 5664, 7051, 725, 6032, 6701, 6160, 5491, 5937, 6273, 1875, 6114, 
5477, 6528, 5573, 4936, 6705, 2180, 3758, 5527, 5368, 5814, 7328, 7424, 429, 5991, 1434, 
6391, 6200, 7283, 5868, 5900, 228, 4085, 6109, 1106, 5791, 692, 6095, 7210, 2893, 1188, 
6814, 4217, 5572, 3757, 5813, 3694, 796, 605, 6486, 128, 4144, 5722, 5754, 1915, 5676, 
5549, 5581, 4976, 5917, 5822, 2174, 6158, 1633, 4566, 5267, 4885, 4503, 1874, 6113, 5476, 
4425, 4871, 5526, 6531, 7886, 1496, 5194, 127, 4780, 5721)

該字符串由以下方法創建,然后將其異步發送到服務器。 我知道這種方法存在一個問題,但是我還沒有時間來討論這個問題並提出更好的解決方案。 我正在使用responsesToSelector和performSelector根據我們從中收集詳細信息的表來處理其他方法。

- (void)processRequest
{
    if( requestQueue.count == 0 )
        return;

    if( processingQueue.count > 3 )
        return;

    Request *request = requestQueue[0];
    [requestQueue removeObjectAtIndex:0];
    DADataTable *source = request.source;
    NSString *destTableName = request.destTableName;
    NSString *sourceKey = request.sourceKey;
    NSString *query = request.query;
    NSArray *destKeys = request.destKeys;
    NSString *originMethodName = request.originMethodName;
    NSArray *destinationMethods = request.destinationMethods;
    NSString *message = request.loadingMessage;

    [[NSNotificationCenter defaultCenter] postNotificationName:@"GATHERINGDATA" object:nil];


    // Cycle through the rows in the source table and extract the keys we need.
    // originMethodName is needed because some tables require additional checks
    // to determine what kind of key we are working with
    // sourceKey is the string that holds the key we're looking for, which is
    // used on tables that don't need specific filtering
    NSSet *set = [self getSourceSet:source originMethodName:originMethodName sourceKey:sourceKey];

    // getLists takes the set generated by getSourceSet and converts the list of
    // ids into a comma separated list of items suitable for passing into a query
    // Currently there is a 1400 item limit per list to keep from exceeding the server
    // limit, which is currently 1500
    NSArray *lists = [self getLists:set];

    NSString *msg = @"Loading Data";
    NSLog(@"%@", message);
    for( NSString *tList in lists ) {
        if( tList.length == 0 ) {
             NSLog(@"%@ not needed", originMethodName);
             continue;
        }

        query = [query stringByAppendingFormat:@"%@)", tList];

        NSLog(@"%@: %@", destTableName, query);
        DAAsyncRequest __block *r = [fda beginGetDataTableWithSQL:query withBlock:^(DADataTable *table){
             DADataTable *destination = [tables valueForKey:destTableName];
             if( tables.count == 0 ) destination = table;
             else if( [destination rowCount] > 0 )
                //dispatch_async(queue, ^(){
                [destination mergeTable:table withPrimaryKeys:destKeys];
                //});

             else
                destination = table;

             [[NSUserDefaults standardUserDefaults] setValue:msg forKey:@"LoadingMessage"];
             [[NSNotificationCenter defaultCenter] postNotificationName:InitialViewControllerNotificationLoadingUpdate object:nil];
             [[NSNotificationCenter defaultCenter] postNotificationName:@"UpdateStatus" object:nil];

             //dispatch_async(queue, ^(){
             [tables setValue:destination forKey:destTableName];
             //});

             for( NSString *method in destinationMethods) {
                SEL tMethod = NSSelectorFromString(method);
                if( [self respondsToSelector:tMethod]) {
                    [self performSelector:tMethod withObject:table];
                }
             }


             if( [self busy] &&
                 [[source name] isEqualToString:DataAccessTableCustomer])
             {
                [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"FETCHINGJOB"];
                [[NSNotificationCenter defaultCenter] postNotificationName:@"JOBFETCHED" object:nil];
             }
             if( [[[NSUserDefaults standardUserDefaults] valueForKey:@"FETCHINGCONTACT"] isEqualToString:@"YES"] &&
                ([[source name] isEqualToString:DataAccessTablePerson] ||
                 [[source name] isEqualToString:DataAccessTableOrganization] ||
                 [[source name] isEqualToString:DataAccessTableOrganizationAddress]))
            {
                 [[NSUserDefaults standardUserDefaults] setValue:nil forKey:@"FETCHINGCONTACT"];
                 [[NSNotificationCenter defaultCenter] postNotificationName:@"CONTACTFETCHED" object:nil];
            }
            [processingQueue removeObject:r];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"PROCESSREQUEST" object:nil];
        }];
        [processingQueue addObject:r];
    }
}

在這里的任何幫助將不勝感激! 感謝您抽出寶貴的時間查看。

是。 基本上,黃金法則是: 不要過早優化

但是無論如何。 我的第一個猜測是:將NSString query替換為NSMutableString query 因為您要在堆上創建1500個NSString對象,並且長度總是增加,所以只需要在下一個循環中將它們丟棄即可。 追加時,NSMutalbeString將內存保留更長的時間-並且您始終在與同一個對象通信。 “(然后使用appendFormat沒有重新分配,而不是stringByAppendingFormat分配對象!)

看這里: NSMutableString的-appendString:方法是構建大字符串的有效方法嗎?

使您的CPU爬升到100%以上不一定是一件壞事。 在具有多個核心的設備(iPhone 4s和更高版本)上,CPU利用率是核心數量的100%倍。 因此,在4秒鍾內最大值為200%,在5秒鍾內最大值為400%。

循環執行一堆處理可最大程度地提高該線程上的CPU使用率,因為代碼會以全速運行,直到完成為止。 這是正常且適當的。

您是否看到過時的UI性能? 這就是您需要用來改進的標准。

我的建議是重寫您的代碼以在GCD后台隊列上運行。 首先嘗試使用默認優先級(與UI相同的優先級)。在多核計算機上,這將占用其中一個內核。 但是,在iPhone 4上,這可能會使UI變得遲鈍。 在這種情況下,您可以切換到下一個較低的優先級,這將花費更長的時間,但為UI賦予了更高的優先級。

然后,您可以根據需要優化代碼。 用戶默認值不是在循環中處理狀態數據的最有效方法。 您可以嘗試刪除用戶默認調用,並切換到將數據保存到實例變量中,或者如果需要在對象之間傳遞信息,則保存到數據容器單例中。 同樣,NSNotificationCenter比委托調用,塊調用或簡單方法調用具有更多的開銷。

但是,在您確定需要優化之前,我不會擔心這些事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM