54

ユーザーがさまざまな種類の地図上にトラックと呼ばれる複雑な位置点のリストを表示できるようにする GPS アプリでは、各トラックは 2k から 10k の位置点で構成されます。トラックは、Google 以外のマップ タイプでレンダリングされると、大幅に切り取られ、削除され、パスが単純化されます。これは、メモリ使用量を抑えてパフォーマンスを向上させるためです。通常、最悪の場合でも、変換された位置点を OpenGL パイプラインに送信することになるのは、1,000 (総計) をはるかに下回る数だけです。

Google Maps SDK for iOS を統合するにあたり、当初は独自の OpenGL トラック レンダリング システムを引き続き活用しようとしましたが、競合する OpenGL コンテキストの使用に関する問題に遭遇しました (レンダリングは機能しましたが、GMSMapView を独自の内部 OpenGL リソースに取得できませんでした)。誰かが削除されたメモリに触れずに両方を解放します)。

そのため、GMSPolyline コンストラクトを活用して、Google SDK にトラック レンダリングを実行させようとしていますが、メモリ使用量に関する重大な問題が発生しており、それらを回避するためのガイダンスを探しています。

Xcode Instruments を使用して、合計約 23,000 の位置ポイント (それぞれではない) を持つ約 25 のポリ ラインを作成する際のメモリ使用量を監視しました。ポリ ラインの作成中に、アプリのメモリ使用量が約 14 MB から約 172 MB に増加し、正味のピークは約 158 MB になります。すべてのポリ ラインが作成された直後、メモリ使用量は最終的に約 19 MB に戻り、約 5 MB の累積ネットで安定しているように見えます。お店。

私たちを悩ませているのは、メモリ使用量のピークです。私たちのラボ テストでは 23,000 の位置点しか使用しませんでしたが、実際にはもっと多くの位置点が存在することが多く、 iPhone 5でGoogle マップが約 450 MB を消費した後、iOS はアプリケーションを放棄したようです(当社の内部ポリライン レンダリング システムは約同じテスト ケースで 12 MB)。

明らかに、GMSPolyLine構造体は、私たちが必要とする重い使用法を意図していません。

いくつかのポリ ライン作成ループを個別の自動解放プールでラップしてから、適切なポイントでそれらを排出しようとしましたが、これはメモリ使用に影響しません。ポリ ラインが作成され、制御がメインの実行ループに戻された後のピーク時のメモリ使用量は、まったく変化しませんでした。後でその理由が明らかになりました。Google マップ システムは、ポリ ラインが作成された後の最初の DisplayLink コールバックまでリソースを解放しません。

次の取り組みは、GMSPolyline でプッシュするデータの量を手動で調整することです。おそらく、Google マップに頼って効率的に行うのではなく、独自の境界テスト、クリッピング、剪定、最小化を使用します。

ここでの欠点は、より多くの GMSPolyline オブジェクトが割り当てられたり、割り当て解除されたりすることを意味することです。これは、ユーザーがマップをパン/ズームしている可能性があるためです。これらの各オブジェクトのロケーション ポイントははるかに少なくなりますが、それでも、このアプローチの予期しない結果、多くの GMSPolyline 割り当ておよび割り当て解除の隠れたオーバーヘッドが懸念されます。

問題は、この状況に対処するための最善のアプローチは何かということです.Googleの誰かがGMSPolylineベストプラクティス、上限、ボトルネックなどに光を当てることができますか.

4

1 に答える 1

1

基本的な http リクエストに基づいて、指示に Google API を使用してみませんか。 https://developers.google.com/maps/documentation/directions/ . (ライセンスの条件とリクエスト数を確認してください)。

そして、IOS MKPolyline でデータをプロットします。私はあなたがより良いパフォーマンスを持っていると確信しています。また、測位データについては Google のみに依存します。

Google API からの応答を座標に変換するには、以下のよく知られた方法 (他の投稿から取得) を使用します。

- (NSMutableArray *)parseResponse:(NSDictionary *)response
{
    NSArray *routes = [response objectForKey:@"routes"];
    NSDictionary *route = [routes lastObject];
    if (route) {
        NSString *overviewPolyline = [[route objectForKey: @"overview_polyline"] objectForKey:@"points"];
        return  [self decodePolyLine:overviewPolyline];
    }
    return nil;
}


-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr {

    NSMutableString *encoded = [[NSMutableString alloc]initWithCapacity:[encodedStr length]];
    [encoded appendString:encodedStr];
    [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                options:NSLiteralSearch range:NSMakeRange(0,
                                                                          [encoded length])];
    NSInteger len = [encoded length];
    NSInteger index = 0;
    NSMutableArray *array = [[NSMutableArray alloc] init]; NSInteger lat=0;
    NSInteger lng=0;
    while (index < len) {
        NSInteger b; NSInteger shift = 0; NSInteger result = 0; do {
            b = [encoded characterAtIndex:index++] - 63; result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlat = ((result & 1) ? ~(result >> 1)
                          : (result >> 1)); lat += dlat;
        shift = 0; result = 0; do {
            b = [encoded characterAtIndex:index++] - 63; result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        NSInteger dlng = ((result & 1) ? ~(result >> 1)
                          : (result >> 1)); lng += dlng;
        NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5]; NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
        CLLocation *location = [[CLLocation alloc] initWithLatitude: [latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:location]; }
    return array;
}

Google SDKのパフォーマンスで同様の問題がありましたが、うまくいきました。

于 2014-04-18T13:35:58.563 に答える