2013-03-15 7 views
54

W aplikacji GPS, która pozwala użytkownikowi wyświetlić listę złożonych punktów lokalizacji, które nazywamy ścieżkami na różnych typach map, każda ścieżka może składać się z od 2k do 10k punktów lokalizacji. Ścieżki są obcinane, przycinane i upraszczane za pomocą ścieżek, gdy są renderowane na mapach innych niż Google. Ma to na celu zmniejszenie zużycia pamięci i zwiększenie wydajności. Zwykle kończymy przesyłanie znacznie mniej niż tysiąc (zbiorczych) transformowanych punktów lokalizacji do potoku OpenGL, nawet w najgorszych przypadkach.GMSPolyline bardzo duża kolec pamięci

Podczas integrowania pakietu SDK Google Maps dla systemu iOS, początkowo próbowaliśmy nadal korzystać z naszego własnego systemu renderowania ścieżek OpenGL, ale wystąpiły problemy ze sprzecznym użyciem kontekstowego kontekstu OpenGL (renderowanie działało, ale nie mogliśmy pobrać GMSMapView do i naszego posiadać własne zasoby OpenGL do wydania bez kontaktu z usuniętą pamięcią).

Próbujemy więc wykorzystać konstrukcje GMSPolyline i pozwolić SDK Google na renderowanie ścieżek, ale mamy problemy z używaniem dużych pamięci i szukamy wskazówek dotyczących ich obejścia.

Korzystając z Xcode Instruments, monitorowaliśmy wykorzystanie pamięci podczas tworzenia około 25 linii poli z łączną liczbą punktów o wartości 23k (nie każda). W miarę tworzenia linii poli, wykorzystanie pamięci aplikacji wzrasta z około 14 MB do około 172 MB, a szczyt sieci wynosi około 158 MB. Krótko po utworzeniu wszystkich linii poly, zużycie pamięci ostatecznie spada do około 19 MB i wydaje się stabilne, dla łącznej sieci około 5 MB, więc wydaje się, że każdy punkt lokalizacji wymaga około 220 bajtów (5 MB/23k punktów) do sklep.

To, co nas boli, to wykorzystanie pamięci szczytowej. Podczas gdy nasz test laboratoryjny wykorzystywał tylko 23 punkty lokalizacyjne, w świecie rzeczywistym jest ich o wiele więcej, i iOS wydaje się odrzucać naszą aplikację po Google Maps zużył około 450 MB na iPhonie iPhone 5 (podczas gdy nasze wewnętrzne renderowanie linii wielowierszowej szczyt systemu osiąga około 12 MB dla tego samego przypadku testowego).

Najwyraźniej konstrukt GMSPolyLine nie jest przeznaczony do dużego obciążenia, które jest nam potrzebne.

Próbowaliśmy owijać niektóre pętle tworzenia linii poli z osobnymi pulami autorelease, a następnie drenować je w odpowiednich punktach, ale nie ma to wpływu na wykorzystanie pamięci. Wykorzystanie pamięci szczytowej po utworzeniu poly lines i powrocie kontroli do pętli głównej nie zmieniło się wcale. Później stało się jasne, dlaczego; system Map Google nie zwalnia zasobów do pierwszego wywołania zwrotnego DisplayLink po utworzeniu poly lines.

Nasz następny wysiłek będzie polegał na ręcznym ograniczeniu ilości danych, które przesuniemy w GMSPolyline, prawdopodobnie korzystając z naszego własnego ograniczenia, przycinania, przycinania, minimalizowania, a nie polegania na Google Maps, aby to zrobić skutecznie.

Wadą jest to, że będzie to oznaczać, że wiele obiektów GMSPolyline zostanie przydzielonych i zwolnionych, potencjalnie podczas gdy użytkownik przesunie/powiększy mapę. Każdy z tych obiektów będzie miał o wiele mniej punktów lokalizacji, ale nadal niepokoimy się o nieprzewidziane konsekwencje tego podejścia, ukryty narzut wielu aloków GMSPolyline i zwolnienie.

Pytanie brzmi, jakie jest najlepsze podejście do radzenia sobie z tą sytuacją i czy ktoś z Google może rzucić trochę światła na jakiekolwiek najlepsze praktyki, górne ograniczenia, wąskie gardła itp. GMSPolyline?

+0

Zespół zamierza to zbadać. Odpowiem, gdy otrzymam aktualizację. – skarE

+0

FWIW próbowaliśmy zdławić nasze zgłoszenie GMSPolyLine, a nawet wstępnie przycinać każdą linię poli do mniej niż 1000 punktów. Przy włączonym dławieniu przesyłamy każdą linię polietylową w odległości 50 ms (również w innych interwałach). Jednak skoki pamięci utrzymują się, ponieważ wydaje się, że 2 - 3 sekundy mijają, zanim struktura GMS zacznie zwalniać pamięć. Takie podejście nie wygląda obiecująco. – DS99

+0

Staraliśmy się również wykonać własne testy granic i przycinanie miejsca na ekranie, abyśmy przesłali znacznie więcej, choć znacznie mniejszą liczbę punktów, GMSPolyLines. Jednak to podejście oznacza, że ​​zwalniamy, ponownie wycinamy, a następnie ponownie dodajemy wiele linii za każdym razem, gdy wywoływany jest wywołanie zwrotne [GMSMapViewDelegate didChangeCameraPosition]. Uderzenie wydajności jest o wiele za dużo, ponieważ przycinanie wymaga od nas przekształcenia wielu punktów w przestrzeń ekranu za pomocą [GMSProjection pointForCoordinate], a następnie klipowania, a następnie rozbicia na wiele linii poli i ponownego przesłania współrzędnych .. trochę bałaganu. – DS99

Odpowiedz

1

dlaczego nie próbować używać google API dla kierunku, w oparciu o podstawowe żądania HTTP. https://developers.google.com/maps/documentation/directions/. (sprawdź warunki licencjonowania i liczbę wniosków).

Następnie narysuj dane za pomocą IOS MKPolyline. Jestem pewien, że będziesz miał lepszą wydajność. Będziesz także polegać tylko na Google w danych pozycjonowania.

konwertować odpowiedzi z google API do współrzędnych, należy skorzystać z dobrze znaną metodę (wzięte z innego wątku) poniżej:

- (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; 
} 

miałem podobny problem z występu na google SDK i pracować dla mnie.