Arcgis Engine性能优化三则
Arcgis的东西用了一段时间了,给我的印象很一般,感觉虽然功能很全面,但性能不高,尤其是不够稳定。当然,我相信这里面也有我们自己的因素,ArcObject里那么多可用的对象,也许早有更好用的东西早在那里等着而我却不知道。不过也实在没有时间挨个试过,只能碰到问题逐个研究。
项目里有一个功能,要在一个图层里一次创建几万个甚至几十万个矩形,这个功能在上一个项目里表现比较糟糕,一个是性能不稳定,经常在生成了几万矩形后就把jvm搞挂了,再一个就是性能出奇的差,生成十万个可能要一个小时甚至更多。最近正是夯实代码阶段,就请一个同事看一下,女娃子也不知看了没有,告诉我她觉得挺好用的,性能上也没什么可做的了。没办法自己来吧,没想到运气还不错,很快就大有斩获。想起前一段时间的几个类似的优化处理,一并记下。
早先遇到的第一个性能问题同样跟那几万个矩形有关。这些个矩形覆盖了地图,有一个功能是要查找任意一个地理对象在哪个网格里。ArcEngine就有这个功能,搜索一个地理要素对应的矩形大概要两百多个毫秒,要是搜索一个还好,顶多顿一下也就过去了,问题是要搜索的地理要素很多,所以这个功能经常要执行几个小时。想想也是,要在几万个矩形里找到对应的一个矩形,还是GIS操作,涉及到几何拓扑之类的,花个几百个毫秒也在情理之中,毕竟ArcEngine又不知道你要搜索的具体情景,没法据此进行优化,要快只能自己来做搜索。好在我们这几万个矩形还是比较规矩的,没有重叠。考研究生的时候的数据结构还没忘光,用二分法查找,速度快又好实现,先根据网格的XY坐标给几万个矩形排个序,同样用二分法插入来做;然后根据地理对象的XY坐标用二分法去查。 结果出来后非常理想,虽然在开始要花一段时间给矩形排序,但查找每个地理要素的时间骤减到几个毫秒,花费的时间原来以小时计,现在有十分钟就差不多了,接近立等可取,呵呵。
后来的一个优化比较简单,ArcObject在遍历table里的记录的时候比较慢。那个功能要多次遍历一个表格,原来的实现为了方便,每次都去table里去取,后来改为一次读到list之类的对象中,用的时候直接去取,速度就快多了,速度提高不亚于前一个。
最后是开头提到的那个问题,乍一看代码确实非常简洁,看不出有什么地方可以做优化。分析时先把循环里体分成几段,把各段的执行时间输出。马上就可以发现,大部分段落的执行时间不到一个毫秒,个别段落却可以达到十几个毫秒。调整时间输出语句的位置,缩小这个别段落的长度,很快就定位了耗时最长的几个语句。发现时间竟然是花在创建Point对象上,而且耗时不固定,有时不到一个毫秒,有时要几十个毫秒,看不到ArcObject的源代码,也没法分析具体原因,估计arcgis的技术人员也未必清楚。只能碰运气了。原来的实现是每次创建一个矩形要new四个point对象代表矩形的四个角,现在把创建工作挪到循环外,每次都用这四个对象。再次生成矩形一切正常,看来ArcEngine在insertfeature后就把矩形都创建了,而不是等到flush的时候再根据积攒的point对象去创建。或者已经把point的值存到了别的对象中,总之速度又有了大幅度的提高,同样立等可取。不过稳定性还没解决,JVM内存溢出,这个问题就比较清楚了,下班了,五一有七天呢,呵呵(早就写好了,没想到今天才能帖上去)。
项目里有一个功能,要在一个图层里一次创建几万个甚至几十万个矩形,这个功能在上一个项目里表现比较糟糕,一个是性能不稳定,经常在生成了几万矩形后就把jvm搞挂了,再一个就是性能出奇的差,生成十万个可能要一个小时甚至更多。最近正是夯实代码阶段,就请一个同事看一下,女娃子也不知看了没有,告诉我她觉得挺好用的,性能上也没什么可做的了。没办法自己来吧,没想到运气还不错,很快就大有斩获。想起前一段时间的几个类似的优化处理,一并记下。
早先遇到的第一个性能问题同样跟那几万个矩形有关。这些个矩形覆盖了地图,有一个功能是要查找任意一个地理对象在哪个网格里。ArcEngine就有这个功能,搜索一个地理要素对应的矩形大概要两百多个毫秒,要是搜索一个还好,顶多顿一下也就过去了,问题是要搜索的地理要素很多,所以这个功能经常要执行几个小时。想想也是,要在几万个矩形里找到对应的一个矩形,还是GIS操作,涉及到几何拓扑之类的,花个几百个毫秒也在情理之中,毕竟ArcEngine又不知道你要搜索的具体情景,没法据此进行优化,要快只能自己来做搜索。好在我们这几万个矩形还是比较规矩的,没有重叠。考研究生的时候的数据结构还没忘光,用二分法查找,速度快又好实现,先根据网格的XY坐标给几万个矩形排个序,同样用二分法插入来做;然后根据地理对象的XY坐标用二分法去查。 结果出来后非常理想,虽然在开始要花一段时间给矩形排序,但查找每个地理要素的时间骤减到几个毫秒,花费的时间原来以小时计,现在有十分钟就差不多了,接近立等可取,呵呵。
后来的一个优化比较简单,ArcObject在遍历table里的记录的时候比较慢。那个功能要多次遍历一个表格,原来的实现为了方便,每次都去table里去取,后来改为一次读到list之类的对象中,用的时候直接去取,速度就快多了,速度提高不亚于前一个。
最后是开头提到的那个问题,乍一看代码确实非常简洁,看不出有什么地方可以做优化。分析时先把循环里体分成几段,把各段的执行时间输出。马上就可以发现,大部分段落的执行时间不到一个毫秒,个别段落却可以达到十几个毫秒。调整时间输出语句的位置,缩小这个别段落的长度,很快就定位了耗时最长的几个语句。发现时间竟然是花在创建Point对象上,而且耗时不固定,有时不到一个毫秒,有时要几十个毫秒,看不到ArcObject的源代码,也没法分析具体原因,估计arcgis的技术人员也未必清楚。只能碰运气了。原来的实现是每次创建一个矩形要new四个point对象代表矩形的四个角,现在把创建工作挪到循环外,每次都用这四个对象。再次生成矩形一切正常,看来ArcEngine在insertfeature后就把矩形都创建了,而不是等到flush的时候再根据积攒的point对象去创建。或者已经把point的值存到了别的对象中,总之速度又有了大幅度的提高,同样立等可取。不过稳定性还没解决,JVM内存溢出,这个问题就比较清楚了,下班了,五一有七天呢,呵呵(早就写好了,没想到今天才能帖上去)。