GMSPolyline非常大的记忆秒杀 [英] GMSPolyline very large memory spike

查看:178
本文介绍了GMSPolyline非常大的记忆秒杀的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在GPS应用程序中,用户可以显示我们称之为各种不同类型地图上复杂位置点的列表,每个轨道可以包含2k到10k个位置点。在非Google地图类型中渲染时,轨道会被大量修剪,修剪和路径简化。这是为了保持内存使用率和性能。即使在最糟糕的情况下,我们通常也只能提交远远少于一千个(聚合)转换的位置点到OpenGL管道。



在集成Google Maps SDK for在iOS中,我们最初试图继续利用我们自己的OpenGL轨道渲染系统,但遇到OpenGL上下文冲突的问题(渲染工作,但我们无法让GMSMapView和我们自己的内部OpenGL资源在没有人触及删除的情况下发布记忆)。

因此,我们试图利用GMSPolyline结构,并让Google SDK执行轨道渲染,但是我们遇到了主要的内存使用问题,并且正在寻找使用Xcode Instruments时,我们在创建约25条多线时总共监测了23k个位置点(不是每个点)的内存使用情况。在创建多行的过程中,应用程序内存使用量从约14 MB增加到约172 MB,净峰约为158 MB。在创建所有多行之后不久,内存使用率最终回落到19 MB左右,并且看起来很稳定,累计净值约为5 MB,因此看起来每个位置点需要大约220个字节(5 MB / 23k点)存储。



最让我们震惊的是内存使用高峰。尽管我们的实验室测试仅使用了23k个位置点,但在现实世界中通常还有更多,而iOS似乎在 Google 在iPhone 5上消耗大约450 MB之后抛弃应用程序(而我们的内部多线渲染系统在相同的测试用例下达到12 MB左右)。



显然 GMSPolyLine 构造不适用于我们要求的重量级使用。



我们尝试用独立的自动释放池包装一些多线创建循环,然后耗尽那些在适当的地方,但这对记忆使用没有影响。创建多行后控制返回主运行循环的峰值内存使用完全没有改变。后来它明白了为什么; Google Map系统不会释放资源,直到创建poly行之后的第一个DisplayLink回调。 我们的下一步工作是手动调整我们在GMSPolyline上推送的数据量,可能使用我们自己的边界测试,裁剪,修剪和放大功能。最小化,而不是依靠谷歌地图来有效地做到这一点。



这里的缺点是,它将意味着更多的GMSPolyline对象将被分配和释放,有可能在用户在地图上进行平移/缩放时潜在地分配和释放。这些对象中的每一个都会有更少的位置点,但是我们仍然担心这种方法带来的不可预见的后果,即许多GMSPolyline分配和释放的隐藏开销。



问题是,处理这种情况的最佳方法是什么?谷歌的某个人是否可以对任何 GMSPolyline 最佳实践,上限,瓶颈等等提出一些看法?

解决方案

基于基本的http请求,您为什么不尝试使用google API进行指导? https://developers.google.com/maps/documentation/directions/ 。 (检查请求的许可和nº条件)。

然后用IOS MKPolyline绘制数据。我确信你会有更好的表现。而且你只会依赖谷歌的定位数据。



将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;


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

NSMutableString * encoded = [[NSMutableString alloc] initWithCapacity:[ encodedStr length]];
[encoded appendString:encodedStr];
[编码replaceOccurrencesOfString:@\\\\withString:@\\
选项:NSLiteralSearch范围:NSMakeRange(0,
[编码长度]) ]。
NSInteger len = [编码长度];
NSInteger index = 0;
NSMutableArray * array = [[NSMutableArray alloc] init]; NSInteger lat = 0;
NSInteger lng = 0;
while(index< len){
NSInteger b; NSInteger shift = 0; NSInteger结果= 0; do {
b = [encoded characterAtIndex:index ++] - 63;结果| =(b& 0x1f)<<转移;
shift + = 5;
} while(b> = 0x20);
NSInteger dlat =((result& 1)?〜(result>> 1)
:(result>> 1)); lat + = dlat;
shift = 0;结果= 0; do {
b = [encoded characterAtIndex:index ++] - 63;结果| =(b& 0x1f)<<转移;
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]; }
返回数组;
}

我在Google sdk上遇到类似的问题,并且它对我很有用。

In a GPS app that allows the user to display a list of complex location points that we call tracks on various different types of map, each track can consist of between 2k to 10k of location points. The tracks are copiously clipped, pruned and path-simplified when they are rendered on non-Google map types. This is to keep memory usage down and performance up. We typically only wind up submitting far less than a thousand (aggregate) transformed location points to the OpenGL pipeline, even in the worst cases.

In integrating the Google Maps SDK for iOS, we initially attempted to continue to leverage our own OpenGL track rendering system, but ran into issues with conflicting OpenGL context usage (rendering worked, but we couldn't get GMSMapView to and our own internal OpenGL resources to both release without someone touching deleted memory).

So we are trying to leverage the GMSPolyline constructs and just let the Google SDK do the track rendering, but we've run into major memory usage issues, and are looking for guidance in working around them.

Using Xcode Instruments, we've monitored memory usage when creating about 25 poly lines with about 23k location points total (not each). Over the course of poly line creation, app memory usage grows from about 14 MB to about 172 MB, a net peak of about 158 MB. Shortly after all the poly lines are created, memory usage finally drops back down to around 19 MB and seems stable, for a cumulative net of around 5 MB, so it seems each location point requires around 220 bytes (5 MB / 23k points) to store.

What hurts us is the peak memory usage. While our laboratory test only used 23k location points, in the real world there are often many more, and iOS seems to jettison our application after Google Maps has consumed around 450 MB on an iPhone 5 (whereas our internal poly line rendering system peaks at around 12 MB for the same test case).

Clearly the GMSPolyLine construct is not intended for the heavy weight usage that we require.

We tried wrapping some of the poly line creation loops with separate autorelease pools, and then draining those at appropriate points, but this has no impact on memory use. The peak memory use after the poly lines are created and control is returned to the main run loop didn't change at all. Later it became clear why; the Google Map system isn't releasing resources until the first DisplayLink callback after the poly lines are created.

Our next effort will be to manually throttle the amount of data we're pushing at GMSPolyline, probably using our own bounds testing, clipping, pruning & minimization, rather than relying on Google Maps to do this efficiently.

The drawback here is that it will mean many more GMSPolyline objects will be allocated and deallocated, potentially while the user is panning/zooming around the map. Each of these objects will have far fewer location points, yet still, we're concerned about unforeseen consequences of this approach, hidden overhead of many GMSPolyline allocs and deallocate.

So the question is, what is the best approach for dealing with this situation, and can someone from Google shed some light on any GMSPolyline best practices, upper bounds, bottlenecks, etc. ?

解决方案

why don´t you try to use google API for direction, based on basic http requests. https://developers.google.com/maps/documentation/directions/ . (check the conditions on licensing and nº of requests).

And then plot the the data with IOS MKPolyline. i´m Sure you will have better performance. And you will only depend on google for the positioning data.

to convert the response from google API to coordinates, use the well known method (taken from other post) below:

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

I had a similar problem with performance on google sdk and it work for me.

这篇关于GMSPolyline非常大的记忆秒杀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆