more cserver work for sharede cache- improvements
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 6 May 2009 12:36:06 +0000 (12:36 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 6 May 2009 12:36:06 +0000 (12:36 +0000)
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@40524 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/evas_cserve_main.c
src/bin/evas_cserve_tool.c
src/lib/cserve/evas_cs.h
src/lib/cserve/evas_cs_client.c
src/lib/engines/common/evas_image_main.c
src/lib/engines/common/evas_image_scalecache.c

index 2500b8d..6b9caf4 100644 (file)
@@ -11,7 +11,7 @@
 // 
 // add ops to get internal cache state (both)
 // preload - make it work (both)
-// monitor /proc/meminfo and if mem low - free items until cache empty (server)
+
 // 
 // pants!
 
@@ -29,6 +29,7 @@ struct _Img
 {
    Image_Entry ie;
    int ref;
+   int dref;
    int usage;
    Mem *mem;
    const char *key;
@@ -51,6 +52,7 @@ struct _Img
    } image;
    Eina_Bool dead : 1;
    Eina_Bool active : 1;
+   Eina_Bool useless : 1;
 };
 
 // config
@@ -63,7 +65,8 @@ static Evas_Cache_Image *cache = NULL;
 static Eina_Hash *active_images = NULL;
 static Eina_List *cache_images = NULL;
 static int cache_usage = 0;
-static int cache_max_usage = 1 * 1024 * 1024;
+static int cache_max_usage = 1 * 1024;
+static int cache_max_adjust = 0;
 static int cache_item_timeout = -1;
 static int cache_item_timeout_check = -1;
 static Mem *stat_mem = NULL;
@@ -88,6 +91,35 @@ get_time(void)
 }
 #endif
 
+static int mem_total = 0;
+static int mem_free = 0;
+static int mem_buffers = 0;
+static int mem_cached = 0;
+
+static void
+meminfo_check(void)
+{
+   FILE *f;
+   char buf[1024];
+   int v;
+   
+   f = fopen("/proc/meminfo", "r");
+   if (!f) return;
+   if (!fgets(buf, sizeof(buf), f)) goto done;
+   v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
+   mem_total = v;
+   if (!fgets(buf, sizeof(buf), f)) goto done;
+   v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
+   mem_free = v;
+   if (!fgets(buf, sizeof(buf), f)) goto done;
+   v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
+   mem_buffers = v;
+   if (!fgets(buf, sizeof(buf), f)) goto done;
+   v = 0; if (sscanf(buf, "%*s %i %*s", &v) != 1) goto done;
+   mem_cached = v;
+   done:
+   fclose(f);
+}
 
 static int stats_dirty = 0;
 static int saved_loads = 0;
@@ -427,7 +459,6 @@ img_loaddata(Img *img)
 {
    double t;
    
-   // fixme: load img data
    t = get_time();
    evas_cache_image_load_data((Image_Entry *)img);
    t = get_time() - t;
@@ -453,7 +484,7 @@ img_free(Img *img)
 static void
 cache_clean(void)
 {
-   while ((cache_usage > cache_max_usage) && (cache_images))
+   while ((cache_usage > ((cache_max_usage + cache_max_adjust) * 1024)) && (cache_images))
      {
         Img *img;
         Eina_List *l;
@@ -487,6 +518,26 @@ cache_timeout(time_t t)
 }
 
 static void
+mem_cache_adjust(void)
+{
+   int pval = cache_max_adjust;
+   int max = 0;
+
+   if (mem_total <= 0) return;
+   if ((mem_free + mem_cached + mem_buffers) < mem_total)
+     cache_max_adjust += mem_total - (mem_free + mem_cached + mem_buffers);
+
+   max = (mem_free / 8) - cache_max_usage;
+   if (max < 0) max = 0;
+   if (max > cache_max_usage) max = cache_max_usage;
+   cache_max_adjust = max - cache_max_usage;
+   
+   if (cache_max_adjust < -cache_max_usage) 
+     cache_max_adjust = -cache_max_usage;
+   if (pval != cache_max_adjust) cache_clean();
+}
+
+static void
 img_cache(Img *img)
 {
    eina_hash_del(active_images, img->key, img);
@@ -499,7 +550,7 @@ img_cache(Img *img)
    cache_images = eina_list_prepend(cache_images, img);
    img->cached = t_now;
    cache_usage += img->usage;
-   if (cache_usage > cache_max_usage)
+   if (cache_usage > ((cache_max_usage + cache_max_adjust) * 1024))
      cache_clean();
 }
 
@@ -596,6 +647,31 @@ img_unload(Img *img)
 }
 
 static void
+img_unloaddata(Img *img)
+{
+   if ((img->dref <= 0) && (img->useless))
+     {
+        Image_Entry *ie = (Image_Entry *)img;
+        
+        evas_cserve_mem_free(img->mem);
+        img->mem = NULL;
+        img->image.data = NULL;
+        img->dref = 0;
+        
+        ie->flags.loaded = 0;
+        ie->allocated.w = 0;
+        ie->allocated.h = 0;
+     }
+}
+
+static void
+img_useless(Img *img)
+{
+   img->useless = 1;
+   if (img->dref <= 0) img_unloaddata(img);
+}
+
+static void
 img_forcedunload(Img *img)
 {
    img->dead = 1;
@@ -725,6 +801,28 @@ message(void *fdata, Server *s, Client *c, int opcode, int size, unsigned char *
              evas_cserve_client_send(c, OP_LOADDATA, sizeof(msg), (unsigned char *)(&msg));
           }
         break;
+     case OP_UNLOADDATA:
+          {
+             Op_Unloaddata *rep;
+             Img *img;
+             
+             rep = (Op_Unloaddata *)data;
+             img = rep->handle;
+             img->dref--;
+             img_unloaddata(img);
+          } 
+        break;
+     case OP_USELESSDATA:
+          {
+             Op_Unloaddata *rep;
+             Img *img;
+             
+             rep = (Op_Unloaddata *)data;
+             img = rep->handle;
+             img->dref--;
+             img_useless(img);
+          } 
+        break;
      case OP_PRELOAD:
           {
              Op_Preload *rep;
@@ -825,7 +923,7 @@ parse_args(int argc, char **argv)
         else if ((!strcmp(argv[i], "-csize")) && (i < (argc - 1)))
           {
              i++;
-             cache_max_usage = atoi(argv[i]) * 1024;
+             cache_max_usage = atoi(argv[i]);
           }
         else if ((!strcmp(argv[i], "-ctime")) && (i < (argc - 1)))
           {
@@ -954,18 +1052,19 @@ main(int argc, char **argv)
         if (exit_flag) break;
         t = time(NULL);
         t_next = t - last_check;
-        if ((t_next) > cache_item_timeout_check)
+        if ((t_next) >= cache_item_timeout_check)
           {
              t_next = cache_item_timeout_check;
              
              last_check = t;
              cache_timeout(t);
+             meminfo_check();
+             mem_cache_adjust();
           }
         if ((t_next <= 0) && (cache_item_timeout_check > 0))
           t_next = 1;
      }
    error:
-   printf("clean shutdown\n");
    if (stat_mem)
      {
         stat_clean(stat_mem);
index 7d10865..ffeb3f9 100644 (file)
@@ -19,10 +19,10 @@ main(int argc, char **argv)
             (!strcmp(argv[i], "--help")))
           {
              printf("Options:\n"
-                    "\t-h                                  This help\n"
-                    "\tgetconfig                           Get configuration values\n"
-                    "\tsetconfig csize ctimeout ctimecheck Set the config values\n"
-                    "\tgetstats                            Get current cache statistics\n"
+                    "\t-h                               This help\n"
+                    "\tgetconfig                        Get configuration values\n"
+                    "\tsetconfig CSIZE CTIME CTIMECHECK Set the config values\n"
+                    "\tgetstats                         Get current cache statistics\n"
                     );
              exit(0);
           }
@@ -35,7 +35,7 @@ main(int argc, char **argv)
                   printf("ERROR: cannot fetch config.\n");
                   exit(-1);
                }
-             printf("csize: %i\n", config.cache_max_usage / 1024);
+             printf("csize: %i\n", config.cache_max_usage);
              printf("ctime: %i\n", config.cache_item_timeout);
              printf("ctimecheck: %i\n", config.cache_item_timeout_check);
              printf("-OK-\n");
@@ -45,7 +45,7 @@ main(int argc, char **argv)
              Op_Setconfig config;
              
              i++;
-             config.cache_max_usage = atoi(argv[i]) * 1024;
+             config.cache_max_usage = atoi(argv[i]);
              i++;
              config.cache_item_timeout = atoi(argv[i]);
              i++;
index a613190..ea7fb87 100644 (file)
@@ -100,15 +100,17 @@ enum
      OP_LOAD, // 2
      OP_UNLOAD, // 3
      OP_LOADDATA, // 4
-     OP_PRELOAD, // 5
-     OP_FORCEDUNLOAD, // 6
+     OP_UNLOADDATA, // 5
+     OP_USELESSDATA, // 6
+     OP_PRELOAD, // 7
+     OP_FORCEDUNLOAD, // 8
      
-     OP_GETCONFIG, // 7
-     OP_SETCONFIG, // 8
-     OP_GETSTATS, // 9
-     OP_GETINFO, // 10
+     OP_GETCONFIG, // 9
+     OP_SETCONFIG, // 10
+     OP_GETSTATS, // 11
+     OP_GETINFO, // 12
      
-   OP_INVALID // 6
+   OP_INVALID // 13
 };
 
 typedef struct
@@ -143,6 +145,10 @@ typedef struct
 typedef struct
 {
    void *handle;
+} Op_Unloaddata;
+typedef struct
+{
+   void *handle;
 } Op_Loaddata;
 typedef struct
 {
@@ -198,6 +204,8 @@ EAPI int       evas_cserve_use_get(void);
 EAPI void      evas_cserve_shutdown(void);
 EAPI Eina_Bool evas_cserve_image_load(Image_Entry *ie, const char *file, const char *key, RGBA_Image_Loadopts *lopt);
 EAPI Eina_Bool evas_cserve_image_data_load(Image_Entry *ie);
+EAPI void      evas_cserve_image_unload(Image_Entry *ie);
+EAPI void      evas_cserve_image_useless(Image_Entry *ie);
 EAPI void      evas_cserve_image_free(Image_Entry *ie);
 EAPI Eina_Bool evas_cserve_config_get(Op_Getconfig_Reply *config);
 EAPI Eina_Bool evas_cserve_config_set(Op_Setconfig *config);
index 6a3ab43..d04631d 100644 (file)
@@ -282,12 +282,43 @@ evas_cserve_image_free(Image_Entry *ie)
    if (ie->data1 == NULL) return;
    memset(&msg, 0, sizeof(msg));
    msg.handle = ie->data1;
-   if (ie->data2) evas_cserve_mem_close(ie->data2);
-   ie->data2 = NULL;
+   if (ie->data2) evas_cserve_image_unload(ie);
    server_send(cserve, OP_UNLOAD, sizeof(msg), (unsigned char *)(&msg));
    ie->data1 = NULL;
 }
 
+EAPI void
+evas_cserve_image_unload(Image_Entry *ie)
+{
+   Op_Unloaddata msg;
+   
+   if (csrve_init > 0) server_reinit();
+   else return;
+   if (!cserve) return;
+   if (ie->data1 == NULL) return;
+   memset(&msg, 0, sizeof(msg));
+   msg.handle = ie->data1;
+   if (ie->data2) evas_cserve_mem_close(ie->data2);
+   ie->data2 = NULL;
+   server_send(cserve, OP_UNLOADDATA, sizeof(msg), (unsigned char *)(&msg));
+}
+
+EAPI void
+evas_cserve_image_useless(Image_Entry *ie)
+{
+   Op_Unloaddata msg;
+   
+   if (csrve_init > 0) server_reinit();
+   else return;
+   if (!cserve) return;
+   if (ie->data1 == NULL) return;
+   memset(&msg, 0, sizeof(msg));
+   msg.handle = ie->data1;
+   if (ie->data2) evas_cserve_mem_close(ie->data2);
+   ie->data2 = NULL;
+   server_send(cserve, OP_USELESSDATA, sizeof(msg), (unsigned char *)(&msg));
+}
+
 EAPI Eina_Bool
 evas_cserve_config_get(Op_Getconfig_Reply *config)
 {
index 00976ac..0640ee7 100644 (file)
@@ -173,8 +173,9 @@ evas_common_rgba_image_unload(Image_Entry *ie)
    evas_cache_image_preload_cancel(ie, NULL);
    
    if (!ie->flags.loaded) return;
-   if (!ie->info.module) return;
+   if ((!ie->info.module) && (!ie->data1)) return;
    if (!ie->file) return;
+   
    ie->flags.loaded = 0;
 
    if ((im->cs.data) && (im->image.data))
@@ -190,6 +191,17 @@ evas_common_rgba_image_unload(Image_Entry *ie)
      }
    im->cs.data = NULL;
 
+#ifdef EVAS_CSERVE
+   if (ie->data1)
+     {
+        evas_cserve_image_useless(ie);
+        im->image.data = NULL;
+        ie->allocated.w = 0;
+        ie->allocated.h = 0;
+        return;
+     }
+#endif   
+   
    if (im->image.data && !im->image.no_free)
      free(im->image.data);
    im->image.data = NULL;
index 473d698..76cf5ff 100644 (file)
 
 #define MAX_SCALEITEMS 32
 #define MIN_SCALE_USES 3
-#define MIN_SCALE_AGE_GAP 5000
-#define MIN_SCALECACHE_SIZE 3200
+//#define MIN_SCALE_AGE_GAP 5000
+#define MAX_SCALECACHE_DIM 3200
 #define FLOP_ADD 4
 #define MAX_FLOP_COUNT 16
 #define FLOP_DEL 1
-//#define SCALE_CACHE_SIZE 10 * 1024 * 1024
-#define SCALE_CACHE_SIZE 0
+#define SCALE_CACHE_SIZE 4 * 1024 * 1024
+//#define SCALE_CACHE_SIZE 0
 
 typedef struct _Scaleitem Scaleitem;
 
@@ -30,7 +30,11 @@ struct _Scaleitem
    RGBA_Image *im, *parent_im;
    int src_x, src_y, src_w, src_h;
    int dst_w, dst_h;
-   int smooth, populate_me, flop;
+   int flop;
+   int size_adjust;
+   Eina_Bool forced_unload : 1;
+   Eina_Bool smooth : 1;
+   Eina_Bool populate_me : 1;
 };
 
 #ifdef SCALECACHE
@@ -96,7 +100,10 @@ evas_common_rgba_image_scalecache_dirty(Image_Entry *ie)
 //             printf(" 0- %i\n", sci->dst_w * sci->dst_h * 4);
              LKL(cache_lock);
              evas_common_rgba_image_free(&sci->im->cache_entry);
-             cache_size -= sci->dst_w * sci->dst_h * 4;
+             if (!sci->forced_unload)
+               cache_size -= sci->dst_w * sci->dst_h * 4;
+             else
+               cache_size -= sci->size_adjust;
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
              LKU(cache_lock);
           }
@@ -201,7 +208,10 @@ _sci_find(RGBA_Image *im,
         if (sci->im)
           {
              evas_common_rgba_image_free(&sci->im->cache_entry);
-             cache_size -= sci->dst_w * sci->dst_h * 4;
+             if (!sci->forced_unload)
+               cache_size -= sci->dst_w * sci->dst_h * 4;
+             else
+               cache_size -= sci->size_adjust;
 //             printf(" 1- %i\n", sci->dst_w * sci->dst_h * 4);
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
           }
@@ -252,7 +262,10 @@ _cache_prune(Scaleitem *notsci, Evas_Bool copies_only)
              sci->usage = 0;
              sci->usage_count = 0;
              sci->flop += FLOP_ADD;
-             cache_size -= sci->dst_w * sci->dst_h * 4;
+             if (!sci->forced_unload)
+               cache_size -= sci->dst_w * sci->dst_h * 4;
+             else
+               cache_size -= sci->size_adjust;
 //             printf(" 2- %i\n", sci->dst_w * sci->dst_h * 4);
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
              memset(sci, 0, sizeof(Eina_Inlist));
@@ -344,8 +357,8 @@ evas_common_rgba_image_scalecache_prepare(Image_Entry *ie, RGBA_Image *dst,
      {
         if (!sci->im)
           {
-             if ((sci->dst_w < MIN_SCALECACHE_SIZE) && 
-                 (sci->dst_h < MIN_SCALECACHE_SIZE))
+             if ((sci->dst_w < MAX_SCALECACHE_DIM) && 
+                 (sci->dst_h < MAX_SCALECACHE_DIM))
                {
                   if (sci->flop <= MAX_FLOP_COUNT)
                     {
@@ -389,6 +402,7 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
    RGBA_Image *im = (RGBA_Image *)ie;
    Scaleitem *sci;
    int didpop = 0;
+   int dounload = 0;
 /*
    static int i = 0;
 
@@ -458,6 +472,44 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
      }
    if (sci->populate_me)
      {
+        int size, osize, used;
+        
+        size = dst_region_w * dst_region_h;
+        if (((dst_region_w > 640) || (dst_region_h > 640)) &&
+            (size > (480 * 480)))
+          {
+             Eina_List *l;
+             Scaleitem *sci2;
+             
+             dounload = 1;
+             osize = sci->parent_im->cache_entry.w * sci->parent_im->cache_entry.h;
+             used = 0;
+             EINA_LIST_FOREACH(im->cache.list, l, sci2)
+               {
+                  if (sci2->im) used += sci2->dst_w * sci2->dst_h;
+               }
+             if ((size < osize) && (used == 0))
+               sci->size_adjust = 0;
+             else
+               {
+                  osize -= used;
+                  if (osize < 0) osize = 0;
+                  size -= osize;
+                  sci->size_adjust = size * 4; 
+               }
+          }
+        else
+          {
+             size *= sizeof(DATA32);
+             if ((cache_size + size) > max_cache_size)
+               {
+                  sci->populate_me = 0;
+                  im->cache.populate_count--;
+               }
+          }
+     }
+   if (sci->populate_me)
+     {
 //        printf("##! populate!\n");
         sci->im = evas_common_image_new
           (dst_region_w, dst_region_h, im->cache_entry.flags.alpha);
@@ -510,11 +562,11 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
                               {
                                  if (yy & 0x1)
                                    {
-                                      if (xx & 0x1) *pp = 0;
+                                      if (xx & 0x1) *pp = 0x882288ff;
                                    }
                                  else
                                    { 
-                                      if (!(xx & 0x1)) *pp = 0;
+                                      if (!(xx & 0x1)) *pp = 0x882288ff;
                                   }
                                  pp++;
                               }
@@ -522,7 +574,15 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
                     }
 #endif                  
                }
-             cache_size += sci->dst_w * sci->dst_h * 4;
+             if (dounload)
+               {
+                  sci->forced_unload = 1;
+                  cache_size += sci->size_adjust;
+               }
+             else
+               {
+                  cache_size += sci->dst_w * sci->dst_h * 4;
+               }
 //             printf(" + %i @ flop: %i (%ix%i)\n", 
 //                    sci->dst_w * sci->dst_h * 4, sci->flop, 
 //                    sci->dst_w, sci->dst_h);
@@ -555,12 +615,20 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
 //               im,
 //               (int)im->cache.orig_usage, 
 //               (int)im->cache.newest_usage);
-        if ((im->cache_entry.flags.loaded) && (!im->cs.no_free) && 
-            (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888))
+        if ((dounload) || 
+            ((im->cache_entry.flags.loaded) && 
+             ((!im->cs.no_free) 
+#ifdef EVAS_CSERVE             
+             || (ie->data1)
+#endif             
+              )  &&
+             (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)))
           {
-             if (im->cache.orig_usage < 
-                 (im->cache.newest_usage / 20))
-               evas_common_rgba_image_unload(&im->cache_entry);
+             if ((dounload) || (im->cache.orig_usage < 
+                                (im->cache.newest_usage / 20)))
+               {
+                  evas_common_rgba_image_unload(&im->cache_entry);
+               }
           }
         LKU(im->cache.lock);
      }