Page MenuHomePhabricator

evas async image load has been broken somewhere during efl 1.23 dev
Open, Showstopper IssuesPublic

Description

This is really bad. evas_object_image_load_head_skip_set() no longer pushes file I/O off to the preload threads. The mainloop will open the file. In fact it loads and opens EVERY file you do a file_set on. The whole point of this was to unblock the mainloop from doing file IO. It's not being done by the main loop thread instead of the worker threads as it was before.

I know it used to before because I especially wrote this to do just that and have been relying on it in many places to speed up things like loading icons in e's menus, loading thumbnails and icons in efm, in rage, etc. etc. and now it's doing the actual open()s in the mainloop causing major stalls where there should be none.

Sample test below. Pass it like 500 images to load. You'll see it's doing syscalls/file IO between ZERO and GO1. It should not be. Certainly not in the mainloop.

Extra bonus points if you now notice that EFL code is totally broken If i add 1000 images on the cmdline. Why? We hit max FD count because we open a file per file_set and keep it around... thus hitting the default 1024 max fd limit easily. So this isn't just a performance drop but a fundamental break in functionality.

/*
gcc show.c -o show `pkg-config --cflags --libs elementary`
 */
#include <Elementary.h>

static Evas_Object *win, *img;

static double t0, t;

static void
win_del(void *data, Evas_Object *obj, void *event_info)
{
   elm_exit();
}

static void
preload(void *data, Evas *e, Evas_Object *obj, void *info)
{
   int iw, ih;
   const char *f;
   double t;

   t = ecore_time_get();
   evas_object_image_file_get(obj, &f, NULL);
   evas_object_image_size_get(obj, &iw, &ih);
   if (!evas_object_image_load_error_get(obj))
     printf("P> %1.5f %s %ix%i\n", t - t0, f, iw, ih);
   else
     printf("E> %1.5f %s\n", t - t0, f);
   if ((iw <= 0) || (ih <= 0)) elm_exit();
   evas_object_resize(obj, iw, ih);
   evas_object_show(obj);
}

int
main(int argc, char **argv)
{
   int i;

   if (argc < 2)
     {
        printf("Args: file.png [preload and head skip]\n");
        return -1;
     }
   elm_init(argc, argv);
   win = elm_win_add(NULL, "show", ELM_WIN_BASIC);
   elm_win_alpha_set(win, EINA_TRUE);
   elm_win_title_set(win, argv[1]);
   evas_object_smart_callback_add(win, "delete,request", win_del, NULL);

   evas_object_resize(img, 320, 320);
   evas_object_resize(win, 320, 320);

   t0 = ecore_time_get();
   t = ecore_time_get();
   ecore_thread_max_set(4);
   printf("ZERO: %1.5f\n", t - t0);
   for (i = 1; i < argc; i++)
     {
        ecore_thread_max_set(4);
        img = evas_object_image_filled_add(evas_object_evas_get(win));
        evas_object_image_load_head_skip_set(img, EINA_TRUE);
        evas_object_event_callback_add(img, EVAS_CALLBACK_IMAGE_PRELOADED,
                                       preload, NULL);
        evas_object_image_file_set(img, argv[i], NULL);
        evas_object_image_preload(img, EINA_FALSE);
     }
   t = ecore_time_get();
   printf("GO1: %1.5f\n", t - t0);

   evas_object_show(win);
   t = ecore_time_get();
   printf("GO2: %1.5f\n", t - t0);
   elm_run();
   elm_shutdown();
   return 0;
}
raster created this task.Oct 16 2019, 8:05 AM
raster triaged this task as Showstopper Issues priority.
raster updated the task description. (Show Details)Oct 16 2019, 12:08 PM