From 0105d034d8ca38c1844d1ceadb95a96b3a35c98e Mon Sep 17 00:00:00 2001 From: raster Date: Thu, 3 Nov 2011 11:07:03 +0000 Subject: [PATCH] From: Kim Yunhan Subject: [E-devel] [elm_map] Fix up too many connections at the same time. Currently, elm_map requests all visible map image tile to map server at the same time. If the scene is turned off while panning or zooming, it will be aborted on HTTP requests. But it already sent to map server, and it already made useless HTTP connections. So if you pan scrolling quickly, elm_map try to download and abort too many HTTP connections repeatedly. If you have stable and high-throughput data connection, it doesn't matter on your side. However map server will get high load, It is sufficient reason to block you. In another case, if you have poor data connection such as 3G connection, it has less throughput and it causes delay of downloading. And finally, the device is as full as HTTP connections even you already aborted. It makes low-performance issue on your device. I wrote a patch for solving this situation. The idea is simple. 1. I limited number of maximum HTTP request on elm_map side. 2. If maximum HTTP request is exceed, keep requests on Eina_List. 3. If each image downloading is completed, try to download recent request. (Because it has strong possibility for your screen) 4. At the same time, invisible request will be removed. (It doesn't make HTTP connection yet) I tested many times on my desktop and device. It works for me. And elm_map's performance is improved appreciably on 3G connections. git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@64685 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33 --- src/lib/elm_map.c | 149 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 48 deletions(-) diff --git a/src/lib/elm_map.c b/src/lib/elm_map.c index c9001dd..460298c 100644 --- a/src/lib/elm_map.c +++ b/src/lib/elm_map.c @@ -45,6 +45,7 @@ typedef struct _Track_Dump Track_Dump; #define PINCH_ZOOM_MIN 0.25 #define PINCH_ZOOM_MAX 4.0 +#define MAX_CONCURRENT_DOWNLOAD 10 #define GPX_NAME "name>" #define GPX_COORDINATES "trkpt " @@ -241,9 +242,11 @@ struct _Elm_Map_Name struct _Grid_Item { Widget_Data *wd; + Grid *g; Evas_Object *img; //Evas_Object *txt; const char *file; + const char *source; struct { int x, y, w, h; } src, out; @@ -298,7 +301,6 @@ struct _Widget_Data } show; int tsize; int nosmooth; - int preload_num; Eina_List *grids; Eina_Bool resized : 1; Eina_Bool on_hold : 1; @@ -362,6 +364,8 @@ struct _Widget_Data Map_Sources_Tab *src; const char *gpx_file; int zoom_min, zoom_max; + Eina_List *download_list; + int download_num; }; struct _Pan @@ -501,6 +505,8 @@ static void grid_clear(Evas_Object *obj, Grid *g); static Grid *grid_create(Evas_Object *obj); static void grid_load(Evas_Object *obj, Grid *g); +static void _process_download_list(Evas_Object *obj); +static void _add_download_list(Evas_Object *obj, Grid_Item *gi); static void _group_object_create(Marker_Group *group); static void _group_object_free(Marker_Group *group); @@ -1147,17 +1153,8 @@ grid_clear(Evas_Object *obj, Grid *g) evas_object_del(gi->img); //evas_object_del(gi->txt); - if (gi->want) - { - gi->want = EINA_FALSE; - wd->preload_num--; - if (!wd->preload_num) - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), - "elm,state,busy,stop", "elm"); - evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL); - } - } + wd->download_list = eina_list_remove(wd->download_list, gi); + gi->want = EINA_FALSE; if (gi->job) { @@ -1170,6 +1167,8 @@ grid_clear(Evas_Object *obj, Grid *g) } if (gi->file) eina_stringshare_del(gi->file); + if (gi->source) + eina_stringshare_del(gi->source); free(gi); } @@ -1201,13 +1200,6 @@ _tile_update(Grid_Item *gi) //evas_object_show(gi->txt); gi->have = EINA_TRUE; - gi->wd->preload_num--; - if (!gi->wd->preload_num) - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), - "elm,state,busy,stop", "elm"); - evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL); - } } static void @@ -1215,10 +1207,15 @@ _tile_downloaded(void *data, const char *file __UNUSED__, int status) { Grid_Item *gi = data; + gi->wd->download_num--; gi->download = EINA_FALSE; gi->job = NULL; - if ((gi->want) && (status == 200)) _tile_update(gi); + if ((gi->want) && (status == 200)) + { + _tile_update(gi); + DBG("DOWNLOAD done %s", gi->file); + } if (status != 200) { @@ -1230,7 +1227,86 @@ _tile_downloaded(void *data, const char *file __UNUSED__, int status) gi->wd->finish_num++; evas_object_smart_callback_call(gi->wd->obj, SIG_DOWNLOADED, NULL); - DBG("DOWNLOAD done %s", gi->file); + if (!gi->wd->download_num) + { + edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr), "elm,state,busy,stop", "elm"); + evas_object_smart_callback_call(gi->wd->obj, SIG_LOADED_DETAIL, NULL); + } + _process_download_list(gi->wd->obj); +} + +static void +_process_download_list(Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Eina_List *l; + Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, tx, ty, gw, gh, xx, yy, ww, hh; + Grid_Item *gi; + + evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh); + evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh); + + gw = wd->size.w; + gh = wd->size.h; + + EINA_LIST_FOREACH(wd->download_list, l, gi) + { + xx = gi->out.x; + yy = gi->out.y; + ww = gi->out.w; + hh = gi->out.h; + + if ((gw != gi->g->w) && (gi->g->w > 0)) + { + tx = xx; + xx = ((long long )gw * xx) / gi->g->w; + ww = (((long long)gw * (tx + ww)) / gi->g->w) - xx; + } + if ((gh != gi->g->h) && (gi->g->h > 0)) + { + ty = yy; + yy = ((long long)gh * yy) / gi->g->h; + hh = (((long long)gh * (ty + hh)) / gi->g->h) - yy; + } + if (!ELM_RECTS_INTERSECT(xx - wd->pan_x + ox, + yy - wd->pan_y + oy, + ww, hh, + cvx, cvy, cvw, cvh)) + { + gi->download = EINA_FALSE; + wd->download_list = eina_list_remove(wd->download_list, gi); + } + } + + EINA_LIST_REVERSE_FOREACH(wd->download_list, l, gi) + { + if (gi->wd->download_num >= MAX_CONCURRENT_DOWNLOAD) + break; + + ecore_file_download_full(gi->source, gi->file, _tile_downloaded, NULL, gi, &(gi->job), wd->ua); + if (!gi->job) + DBG("Can't start to download %s to %s", gi->source, gi->file); + else + { + gi->wd->download_num++; + wd->try_num++; + wd->download_list = eina_list_remove(wd->download_list, gi); + if (wd->download_num == 1) + edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,state,busy,start", "elm"); + } + } +} + +static void +_add_download_list(Evas_Object *obj, Grid_Item *gi) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + + wd->download_list = eina_list_remove(wd->download_list, gi); + wd->download_list = eina_list_append(wd->download_list, gi); + _process_download_list(obj); } static Grid * @@ -1334,15 +1410,6 @@ grid_load(Evas_Object *obj, Grid *g) wd->try_num--; } gi->download = EINA_FALSE; - wd->preload_num--; - if (!wd->preload_num) - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), - "elm,state,busy,stop", "elm"); - evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, - NULL); - } - } else if (gi->have) { @@ -1392,6 +1459,7 @@ grid_load(Evas_Object *obj, Grid *g) gi->out.h = gi->src.h; gi->wd = wd; + gi->g = g; gi->img = evas_object_image_add(evas_object_evas_get(obj)); evas_object_image_scale_hint_set @@ -1431,31 +1499,15 @@ grid_load(Evas_Object *obj, Grid *g) if ((!source) || (strlen(source)==0)) continue; eina_stringshare_replace(&gi->file, buf2); + eina_stringshare_replace(&gi->source, source); if ((ecore_file_exists(buf2)) || (g == eina_list_data_get(wd->grids))) { gi->download = EINA_TRUE; - wd->preload_num++; - if (wd->preload_num == 1) - { - edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), - "elm,state,busy,start", "elm"); - evas_object_smart_callback_call(obj, - SIG_LOAD_DETAIL, - NULL); - } - if (ecore_file_exists(buf2)) _tile_update(gi); else - { - DBG("DOWNLOAD %s \t in %s", source, buf2); - ecore_file_download_full(source, buf2, _tile_downloaded, NULL, gi, &(gi->job), wd->ua); - if (!gi->job) - DBG("Can't start to download %s", buf); - else - wd->try_num++; - } + _add_download_list(obj, gi); } if (source) free(source); } @@ -1481,6 +1533,7 @@ grid_clearall(Evas_Object *obj) grid_clear(obj, g); free(g); } + wd->download_list = eina_list_free(wd->download_list); } static void -- 2.7.4