minimise arrayjoin inputs during processing

arrayjoin with a sequential pipeline will now minimise inputs when they
are no longer being used. This drops the number of open file handles
needed to construct large arrays.

Sadly, memory savings are minimal.

see https://github.com/kleisauke/net-vips/issues/135
This commit is contained in:
John Cupitt 2021-09-06 20:22:29 +01:00
parent 99724e6097
commit a20cd4cdc1
2 changed files with 52 additions and 12 deletions

View File

@ -4,6 +4,7 @@
- fix thumbnail with small image plus crop plus no upsize [Andrewsville]
- rename speed / reduction-effort / etc. params as "effort"
- add gifsave [lovell]
- arrayjoin minimises inputs during processing
16/8/21 started 8.11.4
- fix off-by-one error in new rank fast path

View File

@ -2,6 +2,8 @@
*
* 11/12/15
* - from join.c
* 6/9/21
* - minmise inputs once we've used them
*/
/*
@ -79,25 +81,62 @@ vips_arrayjoin_gen( VipsRegion *or, void *seq,
{
VipsRegion **ir = (VipsRegion **) seq;
VipsArrayjoin *join = (VipsArrayjoin *) b;
VipsConversion *conversion = VIPS_CONVERSION( join );
VipsRect *r = &or->valid;
int n = VIPS_AREA( join->in )->n;
int n;
VipsImage **in;
int i;
gboolean just_one;
/* Does this rect fit within one of our inputs? If it does, we
* can pass just the request on.
*/
for( i = 0; i < n; i++ )
if( vips_rect_includesrect( &join->rects[i], r ) )
return( vips__insert_just_one( or, ir[i],
join->rects[i].left, join->rects[i].top ) );
in = vips_array_image_get( join->in, &n );
/* Output requires more than one input. Paste all touching inputs into
* the output.
/* Does this rect fit completely within one of our inputs?
*/
just_one = FALSE;
for( i = 0; i < n; i++ )
if( vips__insert_paste_region( or, ir[i], &join->rects[i] ) )
return( -1 );
if( vips_rect_includesrect( &join->rects[i], r ) ) {
just_one = TRUE;
break;
}
if( just_one ) {
/* Just needs one input, we can forward the request to that
* region.
*/
if( vips__insert_just_one( or, ir[i],
join->rects[i].left, join->rects[i].top ) )
return( -1 );
}
else {
/* Output requires more than one input. Paste all touching
* inputs into the output.
*/
for( i = 0; i < n; i++ )
if( vips__insert_paste_region( or, ir[i],
&join->rects[i] ) )
return( -1 );
}
if( vips_image_is_sequential( conversion->out ) ) {
/* In sequential mode, we can minimise an input once we've
* fetched the final line of pixels from it.
*
* Find all inputs whose final line is inside this rect and
* shut them down.
*/
for( i = 0; i < n; i++ ) {
VipsRect final_line = {
join->rects[i].left,
VIPS_RECT_BOTTOM( &join->rects[i] ) - 1,
join->rects[i].width,
1
};
if( vips_rect_includesrect( &final_line, r ) )
vips_image_minimise_all( in[i] );
}
}
return( 0 );
}