-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Very slow to open when in a folder with many images #114
Comments
same observation, xviewer 3.0.2 on linux mint 20.2. |
The problem is, that xviewer opens all images in the folder. xviewer is called with something like this:
I guess loading the opened image, display it and then loading the other images in the background would be the better way to do this. Maybe not load all images but just the next 10 or something like this. But i see why this is done. When you have a folder with images and you select only a part of the images and open that, you expect only the selected images to be opened. That is why xviewer is started with a list of files. But still a annoying bug. |
Is this being worked on at all? |
I can confirm this bug exists in xviewer 3.2.10 . Cannot open any images in a directory with ~100k png files when called from bash (e.g. xviewer image.png). No window appears. Console says:
Slightly better behavior than pix, which will open the image and then subsequently lock up cinnamon (probably hitting multiple bugs there). I assume these are related to unwanted "features" triggered by loading a single file, e.g. preparing to slideshow other files in the directory regardless of user intent by loading a totally unpredictable chunk of filesystem into an array.
I did not follow this comment or its logic at all. Opening a file should open a single file and not interact with any other files. |
Im not sure this is the same bug. In the cases i observed, xviewer was called with many images as arguments and did not crash, but took very long (>1min) to load. Especially on slower storage. Does this also happen, if you copy one image out of the folder and open it somewhere, where its less crowded? Also try the As far as i looked into the code it seems to query the content type of each file ( The bad thing is, that if you have enough RAM, Linux will at some point start to cache the file and the latency might disappear. This makes it harder to investigate this problem. Having the media on a external storage device and unplugging it between tests may help. Also filling up the RAM with junk and disabling swap may also help. Maybe there are some kernel parameters to disable this kind of caching? Anyway, this is something to keep in mind while testing. Maybe the best way to implement a fix would be to not process every image at the beginning, but only the 10 next and the 10 previous. This may have the side effect that xviewer shows "Image 1/2000" at the beginning, but after scanning some files, reduces that number, as some of the files may be corrupt, empty or no image at all. A option would be to hide the number until all images where scanned. But even if the number might not be totally correct, i would prefer that over xviewer taking > 1min to open.
I think removing the list of files from xviewer and letting nemo only open one image is not the correct solution as it removes or breaks these features and user experiences:
|
You're right. It is a different bug. I submitted #201.
Don't do anything without any indication of user intent. This is linux. Either that or don't make this the default image viewer in the distribution. As a default viewer, it should load an image in any directory immediately without doing anything else. |
I disagree. An image viewer may allow a user to view neighbouring pictures (and may fetch them to generate a thumbnail), even if they where not directly opened. |
What do you expect the application cat to do when you call |
If i disable the Map plugin from the This is the log with the map plugin and job logging enabled: $ XVIEWER_DEBUG_JOBS=1 xviewer /[path to folder with 7.5k jpg]/[0,000101 (0,000101)] ../src/xviewer-job-scheduler.c:95 (xviewer_job_scheduler_dequeue_job) No jobs in queue [0,000122 (0,000021)] ../src/xviewer-job-scheduler.c:102 (xviewer_job_scheduler_dequeue_job) Wating for jobs ... [0,851012 (0,850890)] ../src/xviewer-jobs.c:771 (xviewer_job_model_new) XviewerJobModel (0x5625f1c80590) job was CREATED [0,851027 (0,000015)] ../src/xviewer-job-scheduler.c:57 (xviewer_job_scheduler_enqueue_job) ENQUEUED XviewerJobModel (0x5625f1c80590) with priority 2 [0,851046 (0,000019)] ../src/xviewer-job-scheduler.c:95 (xviewer_job_scheduler_dequeue_job) DEQUEUED XviewerJobModel (0x5625f1c80590) [0,851060 (0,000014)] ../src/xviewer-job-scheduler.c:147 (xviewer_job_process) PROCESSING a XviewerJobModel (0x5625f1c80590) [5,293605 (4,442545)] ../src/xviewer-job-scheduler.c:95 (xviewer_job_scheduler_dequeue_job) No jobs in queue [5,293620 (0,000015)] ../src/xviewer-job-scheduler.c:102 (xviewer_job_scheduler_dequeue_job) Wating for jobs ... [5,293629 (0,000009)] ../src/xviewer-jobs.c:152 (notify_finished) XviewerJobModel (0x5625f1c80590) job was FINISHED [5,298305 (0,004676)] ../src/xviewer-jobs.c:602 (xviewer_job_load_new) XviewerJobLoad (0x5625f1d70050) job was CREATED [5,298318 (0,000013)] ../src/xviewer-job-scheduler.c:57 (xviewer_job_scheduler_enqueue_job) ENQUEUED XviewerJobLoad (0x5625f1d70050) with priority 2 [5,298333 (0,000015)] ../src/xviewer-job-scheduler.c:95 (xviewer_job_scheduler_dequeue_job) DEQUEUED XviewerJobLoad (0x5625f1d70050) [5,298341 (0,000008)] ../src/xviewer-job-scheduler.c:147 (xviewer_job_process) PROCESSING a XviewerJobLoad (0x5625f1d70050) [5,299127 (0,000786)] ../src/xviewer-jobs.c:117 (notify_progress) XviewerJobLoad (0x5625f1d70050) job update its progress to -> 0,01 [5,401150 (0,102023)] ../src/xviewer-job-scheduler.c:95 (xviewer_job_scheduler_dequeue_job) No jobs in queue [5,401165 (0,000015)] ../src/xviewer-job-scheduler.c:102 (xviewer_job_scheduler_dequeue_job) Wating for jobs ... Cpu usage during the hang is quite low (<3%) but disk reads are at a few MB/s (probably the most my drive has available) After this i closed and reopend xviewer with the same arguments. It now opend in about 7s. I cleared my cache by allocating a very big chunk of random data in memory. Then i run xviewer again. It again took very long to load. But this time i attached with gdb and got a hold of this stacktrace, mentioning (gdb) bt full#0 __GI___libc_read (nbytes=65535, buf=0x560d52f1b010, fd=27) at ../sysdeps/unix/sysv/linux/read.c:26 sc_ret = 65535 sc_cancel_oldtype = 0 sc_ret = <optimized out> #1 __GI___libc_read (fd=27, buf=buf@entry=0x560d52f1b010, nbytes=nbytes@entry=65535) at ../sysdeps/unix/sysv/linux/read.c:24 #2 0x00007f0ef3e0d471 in read (__nbytes=65535, __buf=0x560d52f1b010, __fd=<optimized out>, __fd=<optimized out>, __buf=<optimized out>, __nbytes=<optimized out>) at /usr/include/x86_64-linux-gnu/bits/unistd.h:38 file = 0x560d52631cf0 res = -1 #3 g_local_file_input_stream_read (stream=<optimized out>, buffer=0x560d52f1b010, count=65535, cancellable=0x0, error=0x0) at ../../../gio/glocalfileinputstream.c:153 file = 0x560d52631cf0 res = -1 #4 0x00007f0ef3d511f7 in g_input_stream_read (stream=0x560d52631cf0, buffer=buffer@entry=0x560d52f1b010, count=count@entry=65535, cancellable=cancellable@entry=0x0, error=error@entry=0x0) at ../../../gio/ginputstream.c:198 class = 0x560d523d9130 res = <optimized out> __func__ = "g_input_stream_read" #5 0x00007f0ef3f1d075 in xviewer_image_real_load (error=0x0, job=<optimized out>, data2read=<optimized out>, img=<optimized out>) at ../src/xviewer-image.c:1126 mime_type = <optimized out> buffer = 0x560d52f1b010 "\377\330\377", <incomplete sequence \340> set_metadata = 1 input_stream = 0x560d52631cf0 failed = 0 md_reader = 0x0 bytes_read = <optimized out> use_rsvg = <optimized out> read_image_data = <optimized out> priv = <optimized out> format = <optimized out> loader = <optimized out> bytes_read_total = <optimized out> first_run = 1 read_only_dimension = <optimized out> priv = <optimized out> success = 0 __func__ = "xviewer_image_load" #6 xviewer_image_load (img=<optimized out>, data2read=<optimized out>, job=<optimized out>, error=0x0) at ../src/xviewer-image.c:1437 priv = <optimized out> success = 0 __func__ = "xviewer_image_load" #7 0x00007f0eecdc2589 in () at /usr/lib/xviewer/plugins/libmap.so #8 0x00007f0ef355feba in () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #9 0x00007f0ef35614de in gtk_tree_model_foreach () at /lib/x86_64-linux-gnu/libgtk-3.so.0 #10 0x00007f0eecdc28a6 in () at /usr/lib/xviewer/plugins/libmap.so #14 0x00007f0ef3ca5863 in <emit signal ??? on instance ???> (instance=instance@entry=0x560d52490170, signal_id=<optimized out>, detail=detail@entry=0) at ../../../gobject/gsignal.c:3587 var_args = {{gp_offset = 24, fp_offset = 48, overflow_arg_area = 0x7ffd7474e1a0, reg_save_area = 0x7ffd7474e0e0}} #11 0x00007f0ef3c87d2f in g_closure_invoke (closure=0x560d52ec9da0, return_value=0x0, n_param_values=1, param_values=0x7ffd7474df10, invocation_hint=0x7ffd7474de90) at ../../../gobject/gclosure.c:830 marshal = 0x7f0ef3c8a120 <g_cclosure_marshal_VOID__VOID> marshal_data = 0x0 in_marshal = 0 real_closure = 0x560d52ec9d80 __func__ = "g_closure_invoke" #12 0x00007f0ef3ca3c36 in signal_emit_unlocked_R (node=node@entry=0x560d526acd70, detail=detail@entry=0, instance=instance@entry=0x560d52490170, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffd7474df10) at ../../../gobject/gsignal.c:3777 tmp = <optimized out> handler = 0x560d52ec4b80 accumulator = 0x0 emission = {next = 0x7ffd7474e350, instance = 0x560d52490170, ihint = {signal_id = 221, detail = 0, run_type = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN)}, state = EMISSION_RUN, chain_type = 0x4} class_closure = 0x560d526acd40 hlist = <optimized out> handler_list = 0x560d52ec4b80 return_accu = 0x0 accu = {g_type = 0x0, data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}} signal_id = 221 max_sequential_handler_number = 10021 return_value_altered = 0 #13 0x00007f0ef3ca5614 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffd7474e0c0) at ../../../gobject/gsignal.c:3530 instance_and_params = 0x7ffd7474df10 signal_return_type = <optimized out> param_values = 0x7ffd7474df28 node = <optimized out> i = <optimized out> n_params = <optimized out> __func__ = "g_signal_emit_valist" #15 0x00007f0ef3f41f4f in xviewer_window_obtain_desired_size (image=<optimized out>, width=<optimized out>, height=<optimized out>, window=0x560d52490170) at ../src/xviewer-window.c:1337 screen = <optimized out> monitor = {x = 0, y = 360, width = 1920, height = 1080} allocation = {x = 0, y = 0, width = 540, height = 450} final_width = 460 final_height = 918 screen_width = 1920 screen_height = 1080 window_width = 540 window_height = <optimized out> img_width = <optimized out> img_height = <optimized out> view_width = <optimized out> deco_width = <optimized out> deco_height = <optimized out> __func__ = "xviewer_window_obtain_desired_size" #19 0x00007f0ef3ca5863 in <emit signal ??? on instance ???> (instance=<optimized out>, signal_id=<optimized out>, detail=detail@entry=0) at ../../../gobject/gsignal.c:3587 var_args = {{gp_offset = 40, fp_offset = 48, overflow_arg_area = 0x7ffd7474e6a0, reg_save_area = 0x7ffd7474e5e0}} #16 0x00007f0ef3c87d2f in g_closure_invoke (closure=0x560d5244fbc0, return_value=0x0, n_param_values=3, param_values=0x7ffd7474e3e0, invocation_hint=0x7ffd7474e360) at ../../../gobject/gclosure.c:830 marshal = 0x7f0ef3f13530 <xviewer_marshal_VOID__INT_INT> marshal_data = 0x0 in_marshal = 0 real_closure = 0x560d5244fba0 __func__ = "g_closure_invoke" #17 0x00007f0ef3ca3c36 in signal_emit_unlocked_R (node=node@entry=0x7f0ed012e0d0, detail=detail@entry=0, instance=instance@entry=0x7f0ed02eaca0, emission_return=emission_return@entry=0x0, instance_and_params=instance_and_params@entry=0x7ffd7474e3e0) at ../../../gobject/gsignal.c:3777 tmp = <optimized out> handler = 0x560d5315cc40 accumulator = 0x0 emission = {next = 0x0, instance = 0x7f0ed02eaca0, ihint = {signal_id = 407, detail = 0, run_type = (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN)}, state = EMISSION_RUN, chain_type = 0x4} class_closure = 0x7f0ed012e0a0 hlist = <optimized out> handler_list = 0x560d5315cc40 return_accu = 0x0 accu = {g_type = 0x0, data = {{v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}, {v_int = 0, v_uint = 0, v_long = 0, v_ulong = 0, v_int64 = 0, v_uint64 = 0, v_float = 0, v_double = 0, v_pointer = 0x0}}} signal_id = 407 max_sequential_handler_number = 10001 return_value_altered = 0 #18 0x00007f0ef3ca5614 in g_signal_emit_valist (instance=<optimized out>, signal_id=<optimized out>, detail=<optimized out>, var_args=var_args@entry=0x7ffd7474e5c0) at ../../../gobject/gsignal.c:3530 instance_and_params = 0x7ffd7474e3e0 signal_return_type = <optimized out> param_values = 0x7ffd7474e3f8 node = <optimized out> i = <optimized out> n_params = <optimized out> __func__ = "g_signal_emit_valist" #20 0x00007f0ef3f143e2 in do_emit_size_prepared_signal (img=<optimized out>) at ../src/xviewer-image.c:438 #21 0x00007f0ef3b8ec44 in g_main_dispatch (context=0x560d52320560) at ../../../glib/gmain.c:3419 dispatch = 0x7f0ef3b8aed0 <g_idle_dispatch> prev_source = 0x0 begin_time_nsec = 0 was_in_call = 0 user_data = 0x7f0ed02eaca0 callback = 0x7f0ef3f143c0 <do_emit_size_prepared_signal> cb_funcs = <optimized out> cb_data = <optimized out> need_destroy = <optimized out> source = 0x7f0ed012afe0 current = 0x560d52346ab0 i = 0 #22 g_main_context_dispatch (context=0x560d52320560) at ../../../glib/gmain.c:4137 #23 0x00007f0ef3be42b8 in g_main_context_iterate.constprop.0 (context=context@entry=0x560d52320560, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../../../glib/gmain.c:4213 max_priority = 2147483647 timeout = 11857 some_ready = 1 nfds = <optimized out> allocated_nfds = <optimized out> fds = 0x560d52345840 #24 0x00007f0ef3b8c3e3 in g_main_context_iteration (context=context@entry=0x560d52320560, may_block=may_block@entry=1) at ../../../glib/gmain.c:4278 retval = <optimized out> #25 0x00007f0ef3db3fb5 in g_application_run (application=0x560d52318120, argc=argc@entry=2, argv=argv@entry=0x7ffd7474e958) at ../../../gio/gapplication.c:2569 arguments = 0x560d52345840 status = 0 context = 0x560d52320560 acquired_context = <optimized out> __func__ = "g_application_run" #26 0x0000560d509704bc in main (argc=<optimized out>, argv=<optimized out>) at ../src/main.c:133 error = 0x0 ctx = <optimized out> unfortunately it seems there are no dbg symbols available for xviewer-plugins |
I don't have map enabled, and the load time for a file in a directory with >200k image files is ... too long for me to wait. Minutes, if not hours. A core is pinned at 100% on the process, and the perf says:
So it's probably all this hash table stuff in src/xviewer-metadata-details.c .Sorry, I didn't have the bandwidth to look more closely right now. Somewhere in there must be logic to get metadata from the entire directory, which is problematic. |
Issue
Xviewer takes minutes to open a 1 megapixel image in a folder with many other images (12k in my case). In the same situation, Pix opens instantly.
Xviewer also freezes Thunar until it finally opens. Very frustrating.
Steps to reproduce
Expected behaviour
Should open immediately and work asynchronously from Thunar.
The text was updated successfully, but these errors were encountered: