Merge branch '8.14'
This commit is contained in:
commit
b00a4a80d6
@ -1,9 +1,11 @@
|
|||||||
xx/1/23 8.14.1
|
9/1/23 8.14.1
|
||||||
|
|
||||||
- add vips_thread_isworker() compatibility function [remicollet]
|
- add vips_thread_isworker() compatibility function [remicollet]
|
||||||
- add vips_semaphore_down_timeout() [kleisauke]
|
- add vips_semaphore_down_timeout() [kleisauke]
|
||||||
- idle threads are removed after 15s [kleisauke]
|
- idle threads are removed after 15s [kleisauke]
|
||||||
- fix version number in gtk-doc index [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
|
22/12/22 8.14.0
|
||||||
|
|
||||||
|
@ -67,8 +67,7 @@
|
|||||||
* VipsTextWrap:
|
* VipsTextWrap:
|
||||||
* @VIPS_TEXT_WRAP_WORD: wrap at word boundaries
|
* @VIPS_TEXT_WRAP_WORD: wrap at word boundaries
|
||||||
* @VIPS_TEXT_WRAP_CHAR: wrap at character boundaries
|
* @VIPS_TEXT_WRAP_CHAR: wrap at character boundaries
|
||||||
* @VIPS_TEXT_WRAP_WORD_CHAR: wrap at word boundaries, but fall back to
|
* @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
|
||||||
* character boundaries if there is not enough space for a full word
|
|
||||||
* @VIPS_TEXT_WRAP_NONE: no wrapping
|
* @VIPS_TEXT_WRAP_NONE: no wrapping
|
||||||
*
|
*
|
||||||
* Sets the word wrapping style for vips_text() when used with a maximum
|
* Sets the word wrapping style for vips_text() when used with a maximum
|
||||||
|
@ -37,6 +37,8 @@ create_headers = files(
|
|||||||
'pmask.h',
|
'pmask.h',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
libvips_sources += create_sources
|
||||||
|
|
||||||
create_lib = static_library('create',
|
create_lib = static_library('create',
|
||||||
create_sources,
|
create_sources,
|
||||||
create_headers,
|
create_headers,
|
||||||
|
@ -36,6 +36,8 @@
|
|||||||
* 27/10/22
|
* 27/10/22
|
||||||
* - band interleave ourselves on read
|
* - band interleave ourselves on read
|
||||||
* - don't duplicate metadata
|
* - 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;
|
status = 0;
|
||||||
|
|
||||||
fits->naxis = 3;
|
fits->naxis = in->Bands == 1 ? 2 : 3;
|
||||||
fits->naxes[0] = in->Xsize;
|
fits->naxes[0] = in->Xsize;
|
||||||
fits->naxes[1] = in->Ysize;
|
fits->naxes[1] = in->Ysize;
|
||||||
fits->naxes[2] = in->Bands;
|
fits->naxes[2] = in->Bands;
|
||||||
|
@ -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.
|
/* Swap width and height if we're going to rotate this image.
|
||||||
*/
|
*/
|
||||||
if( jpeg->autorotate &&
|
if( jpeg->autorotate ) {
|
||||||
vips_image_get_orientation_swap( out ) ) {
|
if( vips_image_get_orientation_swap( out ) )
|
||||||
VIPS_SWAP( int, out->Xsize, out->Ysize );
|
VIPS_SWAP( int, out->Xsize, out->Ysize );
|
||||||
|
|
||||||
vips_autorot_remove_angle( out );
|
vips_autorot_remove_angle( out );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,7 @@ vips_thread_main_loop( void *a, void *b )
|
|||||||
!pool->error ) {
|
!pool->error ) {
|
||||||
VIPS_GATE_START( "vips_worker_work_unit: u" );
|
VIPS_GATE_START( "vips_worker_work_unit: u" );
|
||||||
vips_worker_work_unit( worker );
|
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 );
|
vips_semaphore_up( &pool->tick );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@
|
|||||||
#endif /*HAVE_UNISTD_H*/
|
#endif /*HAVE_UNISTD_H*/
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define VIPS_DEBUG
|
||||||
|
*/
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
#include <vips/internal.h>
|
#include <vips/internal.h>
|
||||||
#include <vips/thread.h>
|
#include <vips/thread.h>
|
||||||
@ -105,10 +109,13 @@ vips_threadset_work( void *pointer )
|
|||||||
VipsThreadsetMember *member = (VipsThreadsetMember *) pointer;
|
VipsThreadsetMember *member = (VipsThreadsetMember *) pointer;
|
||||||
VipsThreadset *set = member->set;
|
VipsThreadset *set = member->set;
|
||||||
|
|
||||||
|
VIPS_DEBUG_MSG( "vips_threadset_work: starting %p\n", member );
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
/* Wait for at least 15 seconds to be given work.
|
/* 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;
|
break;
|
||||||
|
|
||||||
/* Killed or no task available? Leave this thread.
|
/* 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->free = g_slist_remove( set->free, member );
|
||||||
set->members = g_slist_remove( set->members, member );
|
set->members = g_slist_remove( set->members, member );
|
||||||
set->n_threads -= 1;
|
set->n_threads -= 1;
|
||||||
|
VIPS_DEBUG_MSG( "vips_threadset_work: stopping %p (%d remaining)\n",
|
||||||
|
member, set->n_threads );
|
||||||
g_mutex_unlock( set->lock );
|
g_mutex_unlock( set->lock );
|
||||||
|
|
||||||
vips_semaphore_destroy( &member->idle );
|
vips_semaphore_destroy( &member->idle );
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python3
|
||||||
|
|
||||||
from __future__ import division
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import cairo
|
import cairo
|
||||||
@ -154,7 +151,7 @@ for thread in threads:
|
|||||||
|
|
||||||
all_events.sort(key=lambda x: x.start)
|
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
|
# move time axis to secs of computation
|
||||||
ticks_per_sec = 1000000.0
|
ticks_per_sec = 1000000.0
|
||||||
@ -173,7 +170,7 @@ for event in all_events:
|
|||||||
last_time = (last_time - first_time) / ticks_per_sec
|
last_time = (last_time - first_time) / ticks_per_sec
|
||||||
first_time = 0
|
first_time = 0
|
||||||
|
|
||||||
print('total time =', last_time)
|
print(f'total time = {last_time}')
|
||||||
|
|
||||||
# calculate some simple stats
|
# calculate some simple stats
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
@ -202,7 +199,7 @@ for thread in threads:
|
|||||||
# hide very short-lived threads
|
# hide very short-lived threads
|
||||||
thread.hide = thread.alive < 0.01
|
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:
|
for thread in threads:
|
||||||
if thread.hide:
|
if thread.hide:
|
||||||
continue
|
continue
|
||||||
@ -211,11 +208,10 @@ for thread in threads:
|
|||||||
work_percent = 100 * thread.work / thread.alive
|
work_percent = 100 * thread.work / thread.alive
|
||||||
unkn_percent = 100 - 100 * (thread.work + thread.wait) / 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((f'{thread.thread_name:>13}\t{thread.alive:6.2f}\t'
|
||||||
print('%.3g\t%.3g\t%.3g\t' %
|
f'{wait_percent:>4.1f}\t{work_percent:>4.1f}\t{unkn_percent:>4.1f}\t'
|
||||||
(wait_percent, work_percent, unkn_percent), end=' ')
|
f'{thread.mem / (1024 * 1024):>4.1f}\t'
|
||||||
print('%.3g\t' % (thread.mem / (1024 * 1024)), end=' ')
|
f'{thread.peak_mem / (1024 * 1024):>4.1f}'))
|
||||||
print('%.3g\t' % (thread.peak_mem / (1024 * 1024)))
|
|
||||||
|
|
||||||
mem = 0
|
mem = 0
|
||||||
peak_mem = 0
|
peak_mem = 0
|
||||||
@ -225,9 +221,9 @@ for event in all_events:
|
|||||||
if mem > peak_mem:
|
if mem > peak_mem:
|
||||||
peak_mem = 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:
|
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?
|
# does a list of events contain an overlap?
|
||||||
# assume the list of events has been sorted by start time
|
# assume the list of events has been sorted by start time
|
||||||
@ -256,6 +252,21 @@ def gates_overlap(events, gate_name1, gate_name2):
|
|||||||
|
|
||||||
return events_overlap(merged)
|
return events_overlap(merged)
|
||||||
|
|
||||||
|
# show top 10 waits
|
||||||
|
wait = {}
|
||||||
|
for thread in threads:
|
||||||
|
for event in thread.all_events:
|
||||||
|
if event.wait:
|
||||||
|
name = f'{event.gate_location}::{event.gate_name}'
|
||||||
|
if name not in wait:
|
||||||
|
wait[name] = 0
|
||||||
|
|
||||||
|
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:>35}\t{time:.2f}')
|
||||||
|
|
||||||
# allocate a y position for each gate
|
# allocate a y position for each gate
|
||||||
total_y = 0
|
total_y = 0
|
||||||
for thread in threads:
|
for thread in threads:
|
||||||
|
Loading…
Reference in New Issue
Block a user