start adding unbuffered sequential mode

This commit is contained in:
John Cupitt 2013-09-27 14:47:04 +01:00
parent 6706fef52b
commit e5ba019942
6 changed files with 110 additions and 17 deletions

57
TODO
View File

@ -1,3 +1,49 @@
- need a new uncached mode for open via disc
currently we have a huge linecache for "vips copy x.png x.v", in
effect what vips does for open-via-disc, and therefore see >100mb ram
use even in open-via-disc mode
add SEQUENTIAL_UNBUFFERED?
could we spot from the demand style? they do almost the same thing,
though one is static and one dynamic, I guess
vips_object_set_argument_from_string() looks at the operation class and
sets ("sequential", TRUE) for image arguments
the "seq" arg needs to be an enum with various settings
"access",
RANDOM, SEQUENTIAL, SEQUENTIAL_UNBUFFERED
todo:
add a new operation flag, try setting it on vips_copy(), pass the flag down
to "access"
in foreign/*.c, evey place that uses vips_sequential() needs to be passed a
copy of "access"
when it calls vips_sequential(), it needs to set an access hint
vips_sequential() needs to pass this down to vips_linecache()
vips_linecache_build() needs to use this to adjust the setting of
max_tiles
- finish hist_ismonotonic()
needs im_conv()
@ -22,17 +68,6 @@
could we add something to check that the two calls agree on the image lists?
I think they should
- need a new uncached mode for open via disc
currently we have a huge linecache for "vips copy x.png x.v", in
effect what vips does for open-via-disc, and therefore see >100mb ram
use even in open-via-disc mode
add SEQUENTIAL_UNBUFFERED?
could we spot from the demand style? they do almost the same thing,
though one is static and one dynamic, I guess
- support multiscan jpeg write? see
https://github.com/jcupitt/ruby-vips/issues/41

View File

@ -135,6 +135,26 @@
* need to swap bytes. See vips_copy().
*/
/**
* VipsForeignAccess:
* @VIPS_FOREIGN_ACCESS_RANDOM: can read anywhere
* @VIPS_FOREIGN_ACCESS_SEQUENTIAL: top-to-bottom reading only, but with a small buffer
* @VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED: top-to-bottom reading only
*
* Set this flag on a loader to indicate the type of access you need.
*
* @VIPS_FOREIGN_ACCESS_RANDOM means you require full random access to the
* image. This is usually the most expensive type of access to provide.
*
* @VIPS_FOREIGN_ACCESS_SEQUENTIAL means you only need need top-to-bottom
* reading, but you need a smll buffer (a few hundred scanlines) behind the
* read point.
*
* @VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED means you only need
* top-to-bottom access. This is usually the cheapest type of access to
* provide.
*/
/**
* VipsForeignClass:
*
@ -685,7 +705,7 @@ vips_foreign_load_temp( VipsForeignLoad *load )
* directly.
*/
if( (load->flags & VIPS_FOREIGN_SEQUENTIAL) &&
load->sequential ) {
load->access != VIPS_FOREIGN_ACCESS_RANDOM ) {
#ifdef DEBUG
printf( "vips_foreign_load_temp: partial sequential temp\n" );
#endif /*DEBUG*/
@ -936,18 +956,27 @@ vips_foreign_load_class_init( VipsForeignLoadClass *class )
G_STRUCT_OFFSET( VipsForeignLoad, disc ),
TRUE );
VIPS_ARG_ENUM( class, "access", 8,
_( "Access" ),
_( "Required access pattern for this file" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignLoad, access ),
VIPS_TYPE_FOREIGN_ACCESS, VIPS_FOREIGN_ACCESS_RANDOM );
VIPS_ARG_BOOL( class, "sequential", 10,
_( "Sequential" ),
_( "Sequential read only" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
G_STRUCT_OFFSET( VipsForeignLoad, sequential ),
FALSE );
}
static void
vips_foreign_load_init( VipsForeignLoad *load )
{
load->disc = TRUE;
load->access = VIPS_FOREIGN_ACCESS_RANDOM;
}
/* Abstract base class for image savers.

View File

@ -9,6 +9,8 @@ G_BEGIN_DECLS
/* enumerations from "../../../libvips/include/vips/foreign.h" */
GType vips_foreign_flags_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_FOREIGN_FLAGS (vips_foreign_flags_get_type())
GType vips_foreign_access_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_FOREIGN_ACCESS (vips_foreign_access_get_type())
GType vips_saveable_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_SAVEABLE (vips_saveable_get_type())
GType vips_foreign_tiff_compression_get_type (void) G_GNUC_CONST;

View File

@ -110,6 +110,12 @@ typedef enum /*< flags >*/ {
(G_TYPE_INSTANCE_GET_CLASS( (obj), \
VIPS_TYPE_FOREIGN_LOAD, VipsForeignLoadClass ))
typedef enum {
VIPS_FOREIGN_ACCESS_RANDOM,
VIPS_FOREIGN_ACCESS_SEQUENTIAL,
VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED
} VipsForeignAccess;
typedef struct _VipsForeignLoad {
VipsForeign parent_object;
/*< private >*/
@ -118,15 +124,18 @@ typedef struct _VipsForeignLoad {
*/
gboolean disc;
/* Setting this means "I promise to only read sequentially from this
* image".
/* Type of access the reader requires.
*/
gboolean sequential;
VipsForeignAccess access;
/* Flags for this load operation.
*/
VipsForeignFlags flags;
/* Deprecated and unused, just here for compat.
*/
gboolean sequential;
/*< public >*/
/* The image we generate. This must be set by ->header().

View File

@ -26,6 +26,24 @@ vips_foreign_flags_get_type( void )
return( etype );
}
GType
vips_foreign_access_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_FOREIGN_ACCESS_RANDOM, "VIPS_FOREIGN_ACCESS_RANDOM", "random"},
{VIPS_FOREIGN_ACCESS_SEQUENTIAL, "VIPS_FOREIGN_ACCESS_SEQUENTIAL", "sequential"},
{VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED, "VIPS_FOREIGN_ACCESS_SEQUENTIAL_UNBUFFERED", "sequential-unbuffered"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsForeignAccess", values );
}
return( etype );
}
GType
vips_saveable_get_type( void )
{
static GType etype = 0;

View File

@ -1535,7 +1535,7 @@ vips_object_set_argument_from_string( VipsObject *object,
*/
if( flags & VIPS_OPERATION_SEQUENTIAL ) {
if( vips_foreign_load_options( value, &out,
"sequential", TRUE,
"access", VIPS_FOREIGN_ACCESS_SEQUENTIAL,
NULL ) )
return( -1 );
}