地图在应用中占用内存是相对较大的一个模块
我们公司因为核心是做轨迹地图和运动数据的分析处理
涉及到多个地图(百度、高德、Apple、Google)各地图间的兼容和转换处理这里就不一一说了 后面单独写篇文章来记录多地图模块的东西
百度/高德地图内存现在版本来说相对会小一些 因为内存做了图层缓存优化处理
Apple原生地图 用过的同学可能会有一些感觉 渲染绘图优美、响应加载绘制快 带来的问题是内存暴涨 因为苹果地图在滑动区域的时候会缓存图层并不释放 导致增长迅速 400+M都有可能(滑动地图持续内存增长)
如果要优化 要么自己释放内存 (据说苹果在内存吃紧时会释放一些地图的资源)
要么在地图不需要显示的时候销毁释放:
1、地图功能界面不显示是停止绘制操作 清空地图上的加载 保存记录清理前的状态 下次进来时再初始化还原
2、在didReceiveMemoryWarning被调用或监测内存警告的通知时 remove掉地图上的元素、对象和地图本身 下次再进入使用时再初始化;状态也是可以记录下来以便下次还原,做到无缝衔接。
具体机制要根据不同的业务需求来做,这里就不赘述了 有问题有好的方式的同学可以留言讨论
苹果地图释放内存
- applyMapViewMemoryRelease是 stackoverflow上看到的方法 猜测原理应该就是转化地图类型后苹果地图会释放缓存的图层 做一部分内存释放 原理原则上不推荐这种方式 如果你觉得无伤大雅 可以接受 可以试试 大概会有1/3的内存减少(也会解决滑动越多内存越大的问题)
据说,假如已退出地图界面,如果app收到内存警告,iOS会把MKMapView占用的内存部分回收, 可以达到50%以上。
//在退出地图的时候可以销毁地图上的所有元素 下次需要再初始化
- (void)destroyMapView
{
_mapView.mapType = MKMapTypeStandard;
_mapView.showsUserLocation = NO;
[_mapView.layer removeAllAnimations];
[_mapView removeAnnotations:_mapView.annotations];
[_mapView removeOverlays:_mapView.overlays];
_mapView.delegate = nil;
[_mapView removeFromSuperview];
_mapView = nil;
[self removeFromSuperview];
}
//在map拖动处理时转换一下地图类型type 能有效释放缓存图层造成的内存暴涨 这不是一个很好的办法 滑动显示区域时会有闪烁
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
[self applyMapViewMemoryRelease];
}
- (void)applyMapViewMemoryRelease{
MKMapType _type = _mapView.mapType;
switch (_mapView.mapType) {
case MKMapTypeHybrid:
{
_mapView.mapType = MKMapTypeStandard;
}
break;
case MKMapTypeStandard:
{
_mapView.mapType = MKMapTypeHybrid;
}
break;
default:
break;
}
_mapView.mapType = _type;
}
至于网上千篇一律说的这种方式我觉得最好还是别这样写
在滑动时会有闪烁的情况 然后重新加载图层 频繁使用不是很好(上面的方法也是👆 不建议放在代理中频繁使用)
- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
[self.mapView removeFromSuperview];
[self addSubview:mapView];
}
点数量的限制
经测试发现 地图上绘制线、点的个数不能超过10w 超过2万多就会有明显的卡顿 10w就会因为内存原因crash
所以一般绘制多点的时候需要做限制或者做采样
地图上加载路线的数量、纹理、渐变图层、annotation animation...都是可以处理的空间
百度地图释放内存
之前有说百度地图内部应该已经做了释放内存的机制处理 我们使用的开发人员应该做的就是遵守他的协定调用viewWillAppear、viewWillDisappear周期来做状态缓存恢复和释放,delegate在不使用的时候一定要置nil
再者就是像上面destroyMapView一样做自己添加一些元素的释放机制处理
/// 地图View的Delegate,此处记得不用的时候需要置nil,否则影响内存的释放
@property (nonatomic, weak) id<BMKMapViewDelegate> delegate;
获取APP内存和CPU使用情况
贴上同事写的内存获取内存和CPU消耗情况 内存数值会偏大于Xcode debug memory 可能是包含了虚拟内存和apple系统共用库的内存情况 自行借鉴吧
//内存使用情况
+ (unsigned long)memoryUsage
{
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size);
if (kr != KERN_SUCCESS) {
return -1;
}
unsigned long memorySize = info.resident_size >> 20;//10-KB 20-MB
// NSLog(@"内存使用情况 %ld",memorySize);
return memorySize;
}
//cpu占用百分比
+ (float)cpu_usage
{
kern_return_t kr = { 0 };
task_info_data_t tinfo = { 0 };
mach_msg_type_number_t task_info_count = TASK_INFO_MAX;
kr = task_info( mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
task_basic_info_t basic_info = { 0 };
thread_array_t thread_list = { 0 };
mach_msg_type_number_t thread_count = { 0 };
thread_info_data_t thinfo = { 0 };
thread_basic_info_t basic_info_th = { 0 };
basic_info = (task_basic_info_t)tinfo; // get threads in the task
kr = task_threads( mach_task_self(), &thread_list, &thread_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
long tot_sec = 0;
long tot_usec = 0;
float tot_cpu = 0;
for ( int i = 0; i < thread_count; i++ )
{
mach_msg_type_number_t thread_info_count = THREAD_INFO_MAX;
kr = thread_info( thread_list[i], THREAD_BASIC_INFO, (thread_info_t)thinfo, &thread_info_count );
if ( KERN_SUCCESS != kr )
return 0.0f;
basic_info_th = (thread_basic_info_t)thinfo;
if ( 0 == (basic_info_th->flags & TH_FLAGS_IDLE) )
{
tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
tot_usec = tot_usec + basic_info_th->system_time.microseconds + basic_info_th->system_time.microseconds;
tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE;
}
}
kr = vm_deallocate( mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t) );
if ( KERN_SUCCESS != kr )
return 0.0f;
// NSLog(@"cpu占用百分比 %f",tot_cpu * 100.);
return tot_cpu * 100.; // CPU 占用百分比
}
暂时先更新到这吧 我比较懒 后面有时间再更新哈 其实做了很多事情 大部分是针对我们地图模块内部业务功能的优化 有童鞋也在做这方面的东西可以留言交流想法 或者有什么好的方案可以分享一下~
网友评论