-
Notifications
You must be signed in to change notification settings - Fork 394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved png memory I/O performance. #241
Conversation
src/memio.h
Outdated
#ifndef LEPTONICA_MEMIO_H | ||
#define LEPTONICA_MEMIO_H | ||
|
||
#include <png.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add here:
#ifdef HAVE_CONFIG_H`
#include "config_auto.h"
#endif /* HAVE_CONFIG_H */
and wrap the rest of the code in:
/* --------------------------------------------*/
#if HAVE_LIBPNG
/* --------------------------------------------*/
#endif /* HAVE_LIBPNG */
/* --------------------------------------------*/
https://github.com/DanBloomberg/leptonica/blob/8a839a254e8d2e/src/pngio.c#L113
The Travis build failed. There are compilation errors. EDIT:
|
src/memio.c
Outdated
* <pre> | ||
* libpng read/write callback replacements for performing memory I/O. | ||
* </pre> | ||
*/#include <string.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, put a linebreak between the /*
and the includes.
Second, in the rest of the codebase #include "allheaders.h"
comes after the cstdlib headers:
https://github.com/DanBloomberg/leptonica/blob/8e7190ccfb46c7/src/pix4.c
To be clear, someone with experience with the build environment needs to make all of these changes.
|
This PR is supposed to solve this Tesseract issue: |
With this change I'm seeing about a 8 - 25% performance boost in Tesseract 4.0.0 LSTM w/OpenMP when passing a bi-tonal bitmap on Windows x64. Visual Studio 2017 was used for the builds. The higher number occurs when concurrency is used to process multiple pages at the same time. The lower number is experienced when performing 1 page OCR and no concurrency. I assume your performance will depend significantly on the number of png images generated as artifacts of the OCR process. I predict the more artifacts that are generated the greater the savings. I notice that the code may be leaking the contents of "state" in error conditions. |
8% improvement of the overall time on a single page seems surprising to me. Can you break this down in terms of read time (both directly to memory and via file) and processing time,for a typical page of text at some stated resolution? |
I understand. I posted because I'm interested in the results of others. I'm running small samples so a little variation can skew a lot. I have here a single page test that just averaged 13.08 over 3 runs without the change, and 3 runs with the change averaged 12.61 seconds. This is a gross measurement of overall time using the Weld .Net wrapper and iterating characters. 4% if I did my math correctly for this sample. Not 8% on that run but consistently measurable. I haven't isolated the measurements into a test harness so I can't break it down by where the time is gained. I seems logical that there should be some gain on Windows given the old implementation. I see leptonica tries to give Windows a hint that the file doesn't actually need to be written but clearly there must be overhead using the temp directory even if the file isn't flushed (directory reads, security checks, file name generation, etc). On systems with fmemopen() I'd have to guess that the two implementations are close to a wash but I have no way of measuring that. |
No question in my mind that for reading and writing via memory, doing it directly is better than via a temporary file and using a file stream interface -- even if the latter is done securely using tmpfile() or similar methods. This should ultimately be enabled for all platforms. Do you have any idea why Microsoft hasn't yet implemented the fmemopen and openmemstream() library functions, which are POSIX 2008? How hard could this be... |
I don't have special insight, but Microsoft hasn't historically had a POSIX focus. Maybe their new cross platform strategies will lead them there. |
src/pngio.c
Outdated
png_textp text_ptr; /* ptr to text_chunk */ | ||
PIX *pix, *pixt; | ||
PIXCMAP *cmap; | ||
struct MemIOData state; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to remote struct
here and simply use MemIOData
.
src/memio.h
Outdated
/* | ||
* <pre>Pointer to the next node in the list. Zero if this is the last node.</pre> | ||
*/ | ||
MemIOData* m_Next; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here struct
is needed because MemIOData
without struct
is still undefined.
src/memio.h
Outdated
* <pre>Pointer to the last node in the linked list. The last node is where new | ||
* content is written.</pre> | ||
*/ | ||
MemIOData* m_Last; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here struct
is needed, see above.
src/pngio.c
Outdated
PIX *pixt; | ||
PIXCMAP *cmap; | ||
char *text; | ||
struct MemIOData state; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove struct
here.
src/memio.c
Outdated
@@ -0,0 +1,181 @@ | |||
/*====================================================================* | |||
- Copyright (C) 2017 Milner Technologies, Inc. This content is a | |||
- component of leptonica and is provided under the terms of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to use the upper case form Leptonica
here and also in the next line.
Those two build errors are caused by missing |
Note also that the code must be strict ANSI C.
And there are some strict guidelines, in particular no asserts (library cannot exit) See also style-guide.txt in the root directory, mostly for formatting. |
@tdhintz, there are compiler options for Visual C which disable the Microsoft extensions. Try |
The project used C++. I don't recall whether I did that or the cmake. I can't think in C so the prototype was C++ and I translated it back to C. Performance with the new vs malloc() was better in a brief test so I left it that way for safety. It is most probable that the difference was due to some factor other than the use of new, but I stuck with the lucky hat. All the suggestions on code format and C compatibility have been diverting but the better question is whether the code improves performance on Win platform. If it doesn't then this exercise has no benefit. |
You mentioned that the memio buffers can have a memory leak with a low-level failure (e.g., causing setjmp). What is the current situation? |
The current commit handles memory correctly on error conditions. |
Let me take a day or two to verify that this will work OK with 'make allheaders', which generates allheaders.h, and that it passes all the regression tests for png I/O -- and I'll merge it as is. After that, I'll need to incorporate memio.{h,c} directly into pngio.c to make its functions static, so that they do not get scooped up into allheaders.h by xtractprotos. And I'll be able to rewrite the now-redundant Stream functions as thin shims of your Mem functions. |
Slightly modified version is in and working. As it turned out, I couldn't easily make the pix read/write stream functions as shims of the mem functions, because the pixa read/write functions are now using the stream interface for each individual pix, and the mem functions are not designed to work consecutively. It's possible to handle this in pixaReadMem(), for example, but it's not clear that it's worth the effort. |
This primarily benefits Tesseract OCR on the Windows platform because it replaces file I/O with memory operations.