babl: free LUTs that have been unused for more than 5 minutes
authorØyvind Kolås <pippin@gimp.org>
Mon, 24 Jan 2022 02:56:09 +0000 (03:56 +0100)
committerØyvind Kolås <pippin@gimp.org>
Mon, 24 Jan 2022 02:56:09 +0000 (03:56 +0100)
babl/babl-fish-path.c
babl/babl-fish.h
babl/base/model-gray.c

index 52e89a4dc628da633a8c0e12bfb28d0fa369e8a3..5660b371d28bccb02325d020d6fad64951eb98ca 100644 (file)
@@ -317,6 +317,9 @@ int
 _babl_fish_path_destroy (void *data)
 {
   Babl *babl=data;
+  if (babl->fish_path.u8_lut)
+    free (babl->fish_path.u8_lut);
+  babl->fish_path.u8_lut = NULL;
   if (babl->fish_path.conversion_list)
     babl_free (babl->fish_path.conversion_list);
   babl->fish_path.conversion_list = NULL;
@@ -663,6 +666,10 @@ babl_fish_path2 (const Babl *source,
       )
      )
   {
+     // as long as the highest 8bit of the 32bit of a 4 byte input is ignored
+     // (alpha) - and it is not an associated color model. A 24 bit LUT provides
+     // exact data. Thus this is valid for instance for "YA half"
+
      if ((source->format.model->flags & BABL_MODEL_FLAG_ASSOCIATED)==0)
        babl->fish_path.is_u8_color_conv = 1;
   }
@@ -711,6 +718,44 @@ babl_fish_path (const Babl *source,
   return babl_fish_path2 (source, destination, 0.0);
 }
 
+typedef struct GcContext {
+   long time;
+} GcContext;
+
+static int gc_fishes (Babl *babl, void *userdata)
+{
+  GcContext *context = userdata;
+  if (babl->class_type == BABL_FISH_PATH)
+  {
+    if (babl->fish_path.u8_lut)
+    {
+      if (context->time - babl->fish_path.last_lut_use >
+          1000 * 1000 * 60 * )
+      {
+        void *lut =babl->fish_path.u8_lut;
+        BABL(babl)->fish_path.u8_lut = NULL;
+        free (lut);
+#if 0
+        fprintf (stderr, "freeing LUT %s to %s unused for >5 minutes\n",
+                        babl_get_name (babl->conversion.source),
+                        babl_get_name (babl->conversion.destination));
+#endif
+      }
+    }
+  }
+  return 0;
+}
+                           
+static void
+babl_gc_fishes (void)
+{
+  GcContext context;
+  context.time = babl_ticks ();
+  babl_fish_class_for_each (gc_fishes, &context);
+  //malloc_trim (0); 
+  //  is responsibility of higher layers
+}
+
 static void
 babl_fish_path_process (const Babl *babl,
                         const char *source,
@@ -821,9 +866,20 @@ babl_fish_path_process (const Babl *babl,
              *dst++ = lut[col & 0xffffff] | (col & 0xff000000);
           }
         }
+        BABL(babl)->fish_path.last_lut_use = babl_ticks ();
         return;
      }
   }
+  else
+  {
+    static long conv_counter = 0;
+    conv_counter+=n;
+    if (conv_counter > 1000 * 1000 * 10) // possibly run gc every 10 megapixels
+    {
+      babl_gc_fishes ();
+      conv_counter = 0;
+    }
+  }
   process_conversion_path (babl->fish_path.conversion_list,
                            source,
                            babl->fish_path.source_bpp,
index 966fa4e32e7798a662b8e22ec0772252311c9886..dfe07a3d7e295929b230d1ddf6e22b1543115fbc 100644 (file)
@@ -71,6 +71,7 @@ typedef struct
   int        dest_bpp;
   unsigned int is_u8_color_conv:1; // keep track of count, and make 
   uint8_t   *u8_lut;
+  long       last_lut_use;
   BablList  *conversion_list;
 } BablFishPath;
 
index 9a74096fbe826deb412a0b859ecf0d9c9c97e79e..7441baae22bfc8c32c65cefe904763ba617de9c2 100644 (file)
@@ -90,7 +90,6 @@ models (void)
     "linear",
     NULL);
 
-
   babl_model_new (
     "id", BABL_GRAY_ALPHA,
     babl_component_from_id (BABL_GRAY_LINEAR),