diff options
author | Robin Watts <robin.watts@artifex.com> | 2016-09-19 13:36:56 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-09-19 16:49:18 +0100 |
commit | 9d430e88deff3e7f0c88ae14edfd0f11331fb53d (patch) | |
tree | ffc4700b884ad7247164ae389c61aafe145608df /source/pdf | |
parent | e22bf36d2db07a3557588ad7cb2d4ccfccb9679f (diff) | |
download | mupdf-9d430e88deff3e7f0c88ae14edfd0f11331fb53d.tar.xz |
fz_store: Reap passes.
A few commits back, we introduced the fz_key_storable concept
to allow us to cope with objects that were used both as values
within the store and as parts of keys within the store.
This commit worked, but showed up performance problems; when the
store has several million PDF objects in it, bulk changes (such
as dropping a display list or document) could trigger many passes
across the store.
We therefore introduce a mechanism to ameliorate this. These
passes, now known as "reap passes", can be batched together using
fz_defer_reap_start and fz_defer_reap_end.
We trigger this start/end around display list dropping, and around
PDF content stream processing. This should be fine, as deferral
will be interrupted if we ever run our of memory during mallocing.
Diffstat (limited to 'source/pdf')
-rw-r--r-- | source/pdf/pdf-interpret.c | 2 | ||||
-rw-r--r-- | source/pdf/pdf-store.c | 3 | ||||
-rw-r--r-- | source/pdf/pdf-xref.c | 83 |
3 files changed, 51 insertions, 37 deletions
diff --git a/source/pdf/pdf-interpret.c b/source/pdf/pdf-interpret.c index f3840794..00c4176c 100644 --- a/source/pdf/pdf-interpret.c +++ b/source/pdf/pdf-interpret.c @@ -1231,12 +1231,14 @@ pdf_process_contents(fz_context *ctx, pdf_processor *proc, pdf_document *doc, pd fz_try(ctx) { + fz_defer_reap_start(ctx); stm = pdf_open_contents_stream(ctx, doc, stmobj); pdf_process_stream(ctx, proc, &csi, stm); pdf_process_end(ctx, proc, &csi); } fz_always(ctx) { + fz_defer_reap_end(ctx); fz_drop_stream(ctx, stm); pdf_clear_stack(ctx, &csi); pdf_lexbuf_fin(ctx, &buf); diff --git a/source/pdf/pdf-store.c b/source/pdf/pdf-store.c index 44575691..33d34ab9 100644 --- a/source/pdf/pdf-store.c +++ b/source/pdf/pdf-store.c @@ -47,7 +47,8 @@ static fz_store_type pdf_obj_store_type = pdf_keep_key, pdf_drop_key, pdf_cmp_key, - pdf_print_key + pdf_print_key, + NULL }; void diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index c4db8e4f..7d21775a 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -1569,54 +1569,65 @@ pdf_drop_document_imp(fz_context *ctx, pdf_document *doc) if (!doc) return; - /* Type3 glyphs in the glyph cache can contain pdf_obj pointers - * that we are about to destroy. Simplest solution is to bin the - * glyph cache at this point. */ - fz_purge_glyph_cache(ctx); + fz_try(ctx) + { + fz_defer_reap_start(ctx); - if (doc->js) - pdf_drop_js(ctx, doc->js); + /* Type3 glyphs in the glyph cache can contain pdf_obj pointers + * that we are about to destroy. Simplest solution is to bin the + * glyph cache at this point. */ + fz_purge_glyph_cache(ctx); - pdf_drop_xref_sections(ctx, doc); - fz_free(ctx, doc->xref_index); + if (doc->js) + pdf_drop_js(ctx, doc->js); - if (doc->focus_obj) - pdf_drop_obj(ctx, doc->focus_obj); - if (doc->file) - fz_drop_stream(ctx, doc->file); - if (doc->crypt) - pdf_drop_crypt(ctx, doc->crypt); + pdf_drop_xref_sections(ctx, doc); + fz_free(ctx, doc->xref_index); - pdf_drop_obj(ctx, doc->linear_obj); - if (doc->linear_page_refs) - { - for (i=0; i < doc->page_count; i++) + if (doc->focus_obj) + pdf_drop_obj(ctx, doc->focus_obj); + if (doc->file) + fz_drop_stream(ctx, doc->file); + if (doc->crypt) + pdf_drop_crypt(ctx, doc->crypt); + + pdf_drop_obj(ctx, doc->linear_obj); + if (doc->linear_page_refs) { - pdf_drop_obj(ctx, doc->linear_page_refs[i]); + for (i=0; i < doc->page_count; i++) + { + pdf_drop_obj(ctx, doc->linear_page_refs[i]); + } + fz_free(ctx, doc->linear_page_refs); } - fz_free(ctx, doc->linear_page_refs); - } - fz_free(ctx, doc->hint_page); - fz_free(ctx, doc->hint_shared_ref); - fz_free(ctx, doc->hint_shared); - fz_free(ctx, doc->hint_obj_offsets); + fz_free(ctx, doc->hint_page); + fz_free(ctx, doc->hint_shared_ref); + fz_free(ctx, doc->hint_shared); + fz_free(ctx, doc->hint_obj_offsets); - for (i=0; i < doc->num_type3_fonts; i++) - { - fz_decouple_type3_font(ctx, doc->type3_fonts[i], (void *)doc); - fz_drop_font(ctx, doc->type3_fonts[i]); - } - fz_free(ctx, doc->type3_fonts); + for (i=0; i < doc->num_type3_fonts; i++) + { + fz_decouple_type3_font(ctx, doc->type3_fonts[i], (void *)doc); + fz_drop_font(ctx, doc->type3_fonts[i]); + } + fz_free(ctx, doc->type3_fonts); - pdf_drop_ocg(ctx, doc->ocg); + pdf_drop_ocg(ctx, doc->ocg); - pdf_empty_store(ctx, doc); + pdf_empty_store(ctx, doc); - pdf_lexbuf_fin(ctx, &doc->lexbuf.base); + pdf_lexbuf_fin(ctx, &doc->lexbuf.base); - pdf_drop_resource_tables(ctx, doc); + pdf_drop_resource_tables(ctx, doc); - fz_free(ctx, doc); + fz_free(ctx, doc); + } + fz_always(ctx) + { + fz_defer_reap_end(ctx); + } + fz_catch(ctx) + fz_rethrow(ctx); } void |