54

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

在集成适用于 iOS 的 Google Maps SDK 时,我们最初尝试继续利用我们自己的 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构造不适用于我们需要的重量级使用。

我们尝试用单独的自动释放池包装一些折线创建循环,然后在适当的点排空它们,但这对内存使用没有影响。创建多段线并将控制权返回到主运行循环后的峰值内存使用根本没有改变。后来很清楚为什么;在创建折线后的第一个 DisplayLink 回调之前,Google 地图系统不会释放资源。

我们接下来的工作将是手动限制我们在 GMSPolyline 推送的数据量,可能使用我们自己的边界测试、裁剪、修剪和最小化,而不是依靠谷歌地图来有效地做到这一点。

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

所以问题是,处理这种情况的最佳方法是什么,谷歌的人能否阐明任何GMSPolyline最佳实践、上限、瓶颈等?

4

1 回答 1

1

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

然后用 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;
}


-(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 回答