From 43a83fcd182fa0962a3e00ab10248e71ab77a9e5 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Jan 2023 12:08:05 +0000 Subject: [PATCH 1/8] a little more dbg output --- libvips/iofuncs/threadset.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libvips/iofuncs/threadset.c b/libvips/iofuncs/threadset.c index 06c91c4b..d0d11ad3 100644 --- a/libvips/iofuncs/threadset.c +++ b/libvips/iofuncs/threadset.c @@ -43,6 +43,10 @@ #endif /*HAVE_UNISTD_H*/ #include +/* +#define VIPS_DEBUG + */ + #include #include #include @@ -105,10 +109,13 @@ vips_threadset_work( void *pointer ) VipsThreadsetMember *member = (VipsThreadsetMember *) pointer; VipsThreadset *set = member->set; + VIPS_DEBUG_MSG( "vips_threadset_work: starting %p\n", member ); + for(;;) { /* Wait for at least 15 seconds to be given work. */ - if( vips_semaphore_down_timeout( &member->idle, max_idle_time ) == -1 ) + if( vips_semaphore_down_timeout( &member->idle, + max_idle_time ) == -1 ) break; /* Killed or no task available? Leave this thread. @@ -150,6 +157,8 @@ vips_threadset_work( void *pointer ) set->free = g_slist_remove( set->free, member ); set->members = g_slist_remove( set->members, member ); set->n_threads -= 1; + VIPS_DEBUG_MSG( "vips_threadset_work: stopping %p (%d remaining)\n", + member, set->n_threads ); g_mutex_unlock( set->lock ); vips_semaphore_destroy( &member->idle ); From 2aea0ee22b0f0dd1dde7066be425a8345cfa0b54 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Jan 2023 14:00:12 +0000 Subject: [PATCH 2/8] update vipsprofile to py3 --- tools/vipsprofile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/vipsprofile b/tools/vipsprofile index f9bbb9f9..812c26ef 100644 --- a/tools/vipsprofile +++ b/tools/vipsprofile @@ -1,7 +1,4 @@ -#!/usr/bin/python - -from __future__ import division -from __future__ import print_function +#!/usr/bin/python3 import re import cairo From 675143807a9cec25a79f3848fb32b67417116db7 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Jan 2023 16:08:57 +0000 Subject: [PATCH 3/8] fix vips_worker_work_unit gate name --- libvips/iofuncs/threadpool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libvips/iofuncs/threadpool.c b/libvips/iofuncs/threadpool.c index 8e392faf..04e57ee0 100644 --- a/libvips/iofuncs/threadpool.c +++ b/libvips/iofuncs/threadpool.c @@ -405,7 +405,7 @@ vips_thread_main_loop( void *a, void *b ) !pool->error ) { VIPS_GATE_START( "vips_worker_work_unit: u" ); vips_worker_work_unit( worker ); - VIPS_GATE_STOP( "vips_thread_work_unit: u" ); + VIPS_GATE_STOP( "vips_worker_work_unit: u" ); vips_semaphore_up( &pool->tick ); } From febb71dba103e634896663e1f37e7eb5dff544c6 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Jan 2023 18:16:04 +0000 Subject: [PATCH 4/8] vipsprofile outputs top 10 waits --- tools/vipsprofile | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/tools/vipsprofile b/tools/vipsprofile index 812c26ef..34cf6c95 100644 --- a/tools/vipsprofile +++ b/tools/vipsprofile @@ -151,7 +151,7 @@ for thread in threads: all_events.sort(key=lambda x: x.start) -print('loaded %d events' % n_events) +print(f'loaded {n_events} events') # move time axis to secs of computation ticks_per_sec = 1000000.0 @@ -170,7 +170,7 @@ for event in all_events: last_time = (last_time - first_time) / ticks_per_sec first_time = 0 -print('total time =', last_time) +print(f'total time = {last_time}') # calculate some simple stats for thread in threads: @@ -199,7 +199,7 @@ for thread in threads: # hide very short-lived threads thread.hide = thread.alive < 0.01 -print('name\t\talive\twait%\twork%\tunkn%\tmemory\tpeakm') +print('name alive wait% work% unkn% mem peakm') for thread in threads: if thread.hide: continue @@ -208,11 +208,10 @@ for thread in threads: work_percent = 100 * thread.work / thread.alive unkn_percent = 100 - 100 * (thread.work + thread.wait) / thread.alive - print('%13s\t%6.2g\t' % (thread.thread_name, thread.alive), end=' ') - print('%.3g\t%.3g\t%.3g\t' % - (wait_percent, work_percent, unkn_percent), end=' ') - print('%.3g\t' % (thread.mem / (1024 * 1024)), end=' ') - print('%.3g\t' % (thread.peak_mem / (1024 * 1024))) + print((f'{thread.thread_name:>13}\t{thread.alive:6.2f}\t' + f'{wait_percent:>4.1f}\t{work_percent:>4.1f}\t{unkn_percent:>4.1f}\t' + f'{thread.mem / (1024 * 1024):>4.1f}\t' + f'{thread.peak_mem / (1024 * 1024):>4.1f}')) mem = 0 peak_mem = 0 @@ -222,9 +221,9 @@ for event in all_events: if mem > peak_mem: peak_mem = mem -print('peak memory = %.3g MB' % (peak_mem / (1024 * 1024))) +print(f'peak memory = {peak_mem / (1024 * 1024):.1f} MB') if mem != 0: - print('leak! final memory = %.3g MB' % (mem / (1024 * 1024))) + print(f'leak! final memory = {mem / (1024 * 1024):.1f} MB') # does a list of events contain an overlap? # assume the list of events has been sorted by start time @@ -253,6 +252,20 @@ def gates_overlap(events, gate_name1, gate_name2): return events_overlap(merged) +# show top 10 waits +wait = {} +for thread in threads: + for event in thread.all_events: + if event.wait: + if event.gate_location not in wait: + wait[event.gate_location] = 0 + + wait[event.gate_location] += event.stop - event.start + +print('name wait') +for [name, time] in sorted(wait.items(), reverse=True, key=lambda x: x[1])[:10]: + print(f'{name:>30}\t{time:.2f}') + # allocate a y position for each gate total_y = 0 for thread in threads: From 8ea519eab76099aacefa346e3af52e7aa0ed3336 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 4 Jan 2023 18:26:41 +0000 Subject: [PATCH 5/8] better wait names in vipsprofile --- tools/vipsprofile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/vipsprofile b/tools/vipsprofile index 34cf6c95..acc0f2e2 100644 --- a/tools/vipsprofile +++ b/tools/vipsprofile @@ -257,14 +257,15 @@ wait = {} for thread in threads: for event in thread.all_events: if event.wait: - if event.gate_location not in wait: - wait[event.gate_location] = 0 + name = f'{event.gate_location}::{event.gate_name}' + if name not in wait: + wait[name] = 0 - wait[event.gate_location] += event.stop - event.start + wait[name] += event.stop - event.start print('name wait') for [name, time] in sorted(wait.items(), reverse=True, key=lambda x: x[1])[:10]: - print(f'{name:>30}\t{time:.2f}') + print(f'{name:>35}\t{time:.2f}') # allocate a y position for each gate total_y = 0 From bd45fbd25c0d8f165fa2e74b892019a02d668dde Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Wed, 4 Jan 2023 20:05:00 +0100 Subject: [PATCH 6/8] Minor GIR fixes (#3261) * Ensure GIR file is aware of `create/` sources It was missing the comments for the `VipsTextWrap` enum. * Avoid new lines in enum members --- libvips/create/create.c | 3 +-- libvips/create/meson.build | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libvips/create/create.c b/libvips/create/create.c index 751bb1f4..c99a4bd3 100644 --- a/libvips/create/create.c +++ b/libvips/create/create.c @@ -67,8 +67,7 @@ * VipsTextWrap: * @VIPS_TEXT_WRAP_WORD: wrap at word boundaries * @VIPS_TEXT_WRAP_CHAR: wrap at character boundaries - * @VIPS_TEXT_WRAP_WORD_CHAR: wrap at word boundaries, but fall back to - * character boundaries if there is not enough space for a full word + * @VIPS_TEXT_WRAP_WORD_CHAR: wrap at word boundaries, but fall back to character boundaries if there is not enough space for a full word * @VIPS_TEXT_WRAP_NONE: no wrapping * * Sets the word wrapping style for vips_text() when used with a maximum diff --git a/libvips/create/meson.build b/libvips/create/meson.build index ed79a13c..4e635de4 100644 --- a/libvips/create/meson.build +++ b/libvips/create/meson.build @@ -37,6 +37,8 @@ create_headers = files( 'pmask.h', ) +libvips_sources += create_sources + create_lib = static_library('create', create_sources, create_headers, From a52b8e36812817c69ef36426978c9bc2790febd9 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 6 Jan 2023 12:06:12 +0000 Subject: [PATCH 7/8] fix mono fits write we should write mono images as naxis=2 see https://github.com/libvips/libvips/issues/3265 --- ChangeLog | 1 + libvips/foreign/fits.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3be50ed7..33eec510 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ xx/1/23 8.14.1 - add vips_semaphore_down_timeout() [kleisauke] - idle threads are removed after 15s [kleisauke] - fix version number in gtk-doc index [kleisauke] +- save mono fits images as NAXIS=2 [ewelot] 22/12/22 8.14.0 diff --git a/libvips/foreign/fits.c b/libvips/foreign/fits.c index 4bce24fb..8c7770a5 100644 --- a/libvips/foreign/fits.c +++ b/libvips/foreign/fits.c @@ -36,6 +36,8 @@ * 27/10/22 * - band interleave ourselves on read * - don't duplicate metadata + * 6/1/23 ewelot + * - save mono images as NAXIS=2 */ /* @@ -658,7 +660,7 @@ vips_fits_set_header( VipsFits *fits, VipsImage *in ) status = 0; - fits->naxis = 3; + fits->naxis = in->Bands == 1 ? 2 : 3; fits->naxes[0] = in->Xsize; fits->naxes[1] = in->Ysize; fits->naxes[2] = in->Bands; From dc78c2c6e4832384e2ac540240388f04d74ca825 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Mon, 9 Jan 2023 10:11:45 +0000 Subject: [PATCH 8/8] fix jpeg autorotate for orientation 3 we were not clearing the orientation tag if width and height were unaltered by the orientation change see https://github.com/libvips/libvips/discussions/3268 thanks zhifengzhuang --- ChangeLog | 3 ++- libvips/foreign/jpeg2vips.c | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 33eec510..bb58dd73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,11 @@ -xx/1/23 8.14.1 +9/1/23 8.14.1 - add vips_thread_isworker() compatibility function [remicollet] - add vips_semaphore_down_timeout() [kleisauke] - idle threads are removed after 15s [kleisauke] - fix version number in gtk-doc index [kleisauke] - save mono fits images as NAXIS=2 [ewelot] +- fix jpeg `autorotate` for orientation 3 [zhifengzhuang] 22/12/22 8.14.0 diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index d494dfb3..aeed07d3 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -979,9 +979,10 @@ vips__jpeg_read( ReadJpeg *jpeg, VipsImage *out, gboolean header_only ) /* Swap width and height if we're going to rotate this image. */ - if( jpeg->autorotate && - vips_image_get_orientation_swap( out ) ) { - VIPS_SWAP( int, out->Xsize, out->Ysize ); + if( jpeg->autorotate ) { + if( vips_image_get_orientation_swap( out ) ) + VIPS_SWAP( int, out->Xsize, out->Ysize ); + vips_autorot_remove_angle( out ); } }