2013-03-15 2 views
54

В приложении GPS, которое позволяет пользователю отображать список сложных точек местоположения, которые мы называем дорожками на разных типах карт, каждый трек может состоять из 2k до 10k точек местоположения. Треки обширно обрезаются, обрезаются и упрощаются, когда они отображаются на картах, отличных от Google. Это необходимо для уменьшения использования памяти и повышения производительности. Как правило, мы заканчиваем передачу гораздо менее тысячи (совокупных) преобразованных точек местоположения в конвейер OpenGL, даже в худших случаях.GMSPolyline очень большой всплеск памяти

При интеграции SDK Google Maps для iOS мы сначала попытались использовать нашу собственную систему рендеринга дорожек OpenGL, но столкнулись с проблемами с конфликтующим контекстом OpenGL (рендеринг работал, но мы не могли получить GMSMapView и наши собственные внутренние ресурсы OpenGL для обоих выпусков, не затрагивая удаленную память).

Итак, мы пытаемся использовать конструкции GMSPolyline и просто даем SDK Google сделать рендеринг дорожки, но мы столкнулись с серьезными проблемами использования памяти и ищем рекомендации по их работе.

Используя Xcode Instruments, мы отслеживали использование памяти при создании около 25 полилиний с общим количеством точек на 23k (не каждый). В ходе создания полилинии использование памяти приложения увеличивается с 14 МБ до 172 МБ, а максимальный пик - около 158 МБ. Вскоре после того, как все полилинии созданы, использование памяти, наконец, опускается примерно до 19 МБ и кажется стабильным, для совокупной сети около 5 МБ, поэтому кажется, что для каждой точки местоположения требуется около 220 байт (5 МБ/23 тыс. Точек) для магазин.

Что нам больно, это пиковое использование памяти. В то время как в нашем лабораторном тесте использовались только локальные точки 23k, в реальном мире их часто бывает много, а iOS, похоже, сбрасывает наше приложение после . Карты Google потребляют около 450 МБ на iPhone 5 (тогда как наша внутренняя поли линия системные пики около 12 МБ для одного и того же теста).

Очевидно, что конструкция GMSPolyLine не предназначена для использования в тяжелых условиях, которые нам требуются.

Мы попытались обернуть некоторые петли создания полилинии с помощью отдельных пулов автоопределения, а затем слив их в соответствующих точках, но это не влияет на использование памяти. Использование пиковой памяти после создания полилиний и возврата в основной цикл запуска не изменилось вообще. Позже стало ясно, почему; система Google Map не освобождает ресурсы до первого обратного вызова DisplayLink после создания полилиний.

Наше следующее усилие состоит в том, чтобы вручную уменьшить объем данных, которые мы нажимаем на GMSPolyline, возможно, используя наши собственные тесты границ, обрезание, обрезку &, а не полагаться на Карты Google, чтобы сделать это эффективно.

Недостатком здесь является то, что это означает, что многие другие объекты GMSPolyline будут выделены и освобождены, потенциально, когда пользователь будет панорамировать/масштабировать вокруг карты. У каждого из этих объектов будет гораздо меньше мест определения местоположения, но все же мы обеспокоены непредвиденными последствиями этого подхода, скрытыми накладными расходами многих GMSPolyline-ассигнований и освобождением.

Итак, вопрос в том, какой подход лучше всего подходит для решения этой ситуации, и может ли кто-то из Google пролить свет на любые лучшие методы, верхние границы, узкие места и т. Д.?

+0

Команда собирается исследовать это. Я отвечу, когда у меня есть обновление для вас. – skarE

+0

FWIW мы пытались дросселировать нашу подачу GMSPolyLine и даже предварительно обрезать каждую полилинию до менее 1000 точек. При включенной дроссельной заслонке мы отправляем каждую поли линию длиной 50 мс (также пробовали другие интервалы). Но всплески памяти сохраняются, так как кажется, что прошло 2 - 3 секунды, прежде чем среда GMS начнет выпускать память. Таким образом, этот подход не выглядит многообещающим. – DS99

+0

Кроме того, мы попытались провести собственное тестирование границ и отсечение экрана, чтобы мы отправляли еще много, хотя и значительно меньше в подсчете очков, GMSPolyLines. Однако этот подход означает, что мы выпускаем, повторно обрезаем, а затем повторно добавляем много поли строк каждый раз, когда срабатывает обратный вызов [GMSMapViewDelegate didChangeCameraPosition]. Снижение производительности слишком велико, потому что для отсечения требуется, чтобы мы преобразовали много точек в пространство экрана с помощью [GMSProjection pointForCoordinate], затем клип, затем разбились на несколько полилиний и повторно передали координаты .. немного беспорядка. – DS99

ответ

1

Почему вы не пытаетесь использовать API Google для направления, основываясь на базовых HTTP-запросах. 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, и это работает для меня.

Смежные вопросы