programing

GMSPolyline 매우 큰 메모리 스파이크

kingscode 2021. 1. 16. 10:01
반응형

GMSPolyline 매우 큰 메모리 스파이크


사용자가 다양한 유형의지도에서 트랙이라고 부르는 복잡한 위치 지점 목록을 표시 할 수있는 GPS 앱에서 각 트랙은 2k에서 10k 사이의 위치 지점으로 구성 될 수 있습니다. 트랙이 Google 이외의지도 유형에서 렌더링 될 때 복사되고 잘리고 경로가 단순화됩니다. 이는 메모리 사용량을 낮추고 성능을 높이기위한 것입니다. 우리는 일반적으로 최악의 경우에도 OpenGL 파이프 라인에 변환 된 위치 포인트를 천 개 (집계)보다 훨씬 적게 제출합니다.

iOS 용 Google지도 SDK를 통합 할 때 처음에는 자체 OpenGL 트랙 렌더링 시스템을 계속 활용하려고 시도했지만 충돌하는 OpenGL 컨텍스트 사용 문제가 발생했습니다 (렌더링이 작동했지만 GMSMapView와 자체 내부 OpenGL 리소스를 가져올 수 없음). 누군가가 삭제 된 메모리를 건드리지 않고 둘 다 해제합니다).

따라서 우리는 GMSPolyline 구조를 활용하고 Google SDK가 트랙 렌더링을 수행하도록하려고 노력하고 있지만 주요 메모리 사용 문제가 발생하여 문제를 해결하기위한 지침을 찾고 있습니다.

Xcode Instruments를 사용하여 총 23k 위치 지점 (각각이 아님)으로 약 25 개의 폴리 라인을 생성 할 때 메모리 사용량을 모니터링했습니다. 폴리 라인 생성 과정에서 앱 메모리 사용량은 약 14MB에서 약 172MB로 증가하여 약 158MB의 순 최고치입니다. 모든 폴리 라인이 생성 된 직후, 메모리 사용량은 마침내 약 19MB로 떨어지고 안정적으로 보이며, 누적 넷은 약 5MB이므로 각 위치 포인트에는 약 220 바이트 (5MB / 23k 포인트)가 필요합니다. 저장.

우리에게 상처를주는 것은 최대 메모리 사용량입니다. 실험실 테스트에서는 23k 위치 지점 만 사용했지만 실제 세계에서는 더 많은 지점이있는 경우가 많으며 iOS는 Google지도iPhone 5 에서 약 450MB를 소비 한 후 애플리케이션을 버리는 것으로 보입니다 (반면 내부 폴리 라인 렌더링 시스템은 동일한 테스트 케이스의 경우 12MB).

분명히 GMSPolyLine구조는 우리가 요구하는 무거운 중량 사용을위한 것이 아닙니다.

일부 폴리 라인 생성 루프를 별도의 자동 릴리스 풀로 래핑 한 다음 적절한 지점에서 드레 이닝하려고 시도했지만 메모리 사용에는 영향을주지 않습니다. 폴리 라인이 생성되고 제어가 메인 런 루프로 돌아간 후 최대 메모리 사용량은 전혀 변경되지 않았습니다. 나중에 이유가 분명해졌습니다. Google지도 시스템은 폴리 라인이 생성 된 후 첫 번째 DisplayLink 콜백이 발생할 때까지 리소스를 해제하지 않습니다.

우리의 다음 노력은 GMSPolyline에서 푸시하는 데이터의 양을 수동으로 조절하는 것입니다.이 작업을 효율적으로 수행하기 위해 Google지도에 의존하는 대신 자체 경계 테스트, 클리핑, 정리 및 최소화를 사용합니다.

여기서 단점은 잠재적으로 사용자가지도 주위를 이동 / 확대하는 동안 더 많은 GMSPolyline 개체가 할당되고 할당 해제된다는 것을 의미합니다. 이러한 각 개체는 훨씬 더 적은 위치 지점을 갖지만 여전히이 접근 방식의 예기치 않은 결과, 많은 GMSPolyline 할당 및 할당 해제의 숨겨진 오버 헤드에 대해 우려하고 있습니다.

따라서 문제는이 상황을 처리하기위한 최선의 접근 방식이 무엇이며 Google의 누군가가 GMSPolyline모범 사례, 상한선, 병목 현상 등에 대해 밝힐 수 있습니까?


기본적인 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의 성능과 비슷한 문제가 있었고 그것은 나를 위해 작동합니다.

참조 URL : https://stackoverflow.com/questions/15442262/gmspolyline-very-large-memory-spike

반응형