【问题标题】:GMSPolyline very large memory spikeGMSPolyline 非常大的内存峰值
【发布时间】:2013-03-04 17:59:04
【问题描述】:

在允许用户显示复杂位置点列表的 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 之后放弃了我们的应用程序 /em>(而对于相同的测试用例,我们的内部折线渲染系统的峰值约为 12 MB)。

显然,GMSPolyLine 构造不适用于我们需要的重量级用法。

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

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

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

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

【问题讨论】:

  • 团队将对此进行调查。当我有更新时,我会回复你。
  • FWIW 我们尝试限制我们的 GMSPolyLine 提交,甚至将每条折线预先修剪到少于 1000 个点。启用节流后,我们每隔 50 毫秒提交每条折线(也尝试过其他间隔)。但是内存峰值仍然存在,因为在 GMS 框架开始释放内存之前似乎 2 到 3 秒过去了。所以这种方法看起来并不乐观。
  • 此外,我们尝试进行自己的边界测试和屏幕空间裁剪,以便提交更多 GMSPolyLines,尽管点数明显减少。然而,这种方法意味着每次触发 [GMSMapViewDelegate didChangeCameraPosition] 回调时,我们都会释放、重新剪辑、然后重新添加许多折线。性能损失太大了,因为剪辑需要我们使用 [GMSProjection pointForCoordinate] 将许多点转换为屏幕空间,然后剪辑,然后分成多条折线并重新提交坐标.. 有点乱。
  • 我有同样的问题 +1 为你的问题
  • 你有没有单独尝试过 GMSPath 类,只是为了评估内存使用情况?

标签: optimization memory-management gps google-maps-sdk-ios


【解决方案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 上遇到了类似的性能问题,它对我有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-19
    相关资源
    最近更新 更多