rmtheis / tess-two

Fork of Tesseract Tools for Android
Apache License 2.0
3.76k stars 1.38k forks source link

TessBaseAPI - clear/end/stop doesn't really free all native memory #227

Closed anonym24 closed 6 years ago

anonym24 commented 7 years ago

Summary: TessBaseAPI - clear/end/stop doesn't really free up all native memory

TessBaseAPI.clear()
TessBaseAPI.stop();
TessBaseAPI.end();

Steps to reproduce the issue:

before initializing TessBaseAPI I usallly have ~10 mb native memory usage:

befor init

When I start initializing my 8 instances of TessBaseAPI (cause TessBaseAPI works with multi-threading ok) with my button (onClick listener)

for (int i = 0; i < mTessArray.length; i++) {
    mTessArray[i] = new TessBaseAPI();
    mTessArrayij].init(mTessDataPath, mLanguageTess);
}

it will allocate + ~90 mb native memory:

tess is init

so now it's around ~100 mb == (~10 + ~90)

but when I releasing all tess instances (I call all clear/stop/end methods for every instance)

if (mTessArray != null) {
   for (int i = 0; i < mTessArray.length; i++) {
            mTessArray[i].clear();
            mTessArray[i].stop();
            mTessArray[i].end();
            mTessArray[i] = null;
    }
    mTessArray = null;
}

it doesn't go back to ~10 mb (as was before initialization tess instances):

tess is release

did free up only ~20 mb

of course the problem is not about many instances, the same behavior would be also only for one instance, I just tested with what I had in my projects (many instances)

so the problem is about freeing up all used memory by tess

Tess-two version: 8.0.0

Android version: 6.0.1

Phone/device model: Redmi 4 Prime/Pro

Phone/device architecture: arm64-v8a (but I use armeabi-v7a so lib files - ndk { abiFilters 'armeabi-v7a' }

anonym24 commented 7 years ago

though it clears much more when I minimize my app (pressing the home button - Activity onPause, onStop methods are called)

rmtheis commented 7 years ago

Nice catch. Interesting. Did you try a test where you force garbage collection such as by calling System.gc() afterwards?

What does the profile look like for calling that sequence of operations repeatedly with a single instance, like doing init->clear->stop->end repeatedly?

anonym24 commented 7 years ago

Tried with one instance in new project:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tesseract_test);

        mTessDataPath = getFilesDir() + "/tesseract/";
        tessCheckFile(new File(mTessDataPath + "tessdata/"));

        // ~3 mb
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mTessArray = new TessBaseAPI();
                mTessArray.init(mTessDataPath, mLanguageTess);
                // ~12 mb

                mTessArray.clear();
                mTessArray.stop();
                mTessArray.end();
                mTessArray = null;
                System.gc();
                // ~10 mb (doesn't go back to ~3 mb)

                mHandler.postDelayed(this, 5000);
            }
        }, 5000);
    }

Same issue, before first Tesseract init I have about ~3 mb native memory used

After Tesseract init it allocates about ~12 mb native After releasing it's ~10 mb (not ~3 mb)

And after every 5 seconds 12, 10... 12, 10.... 12, 10 (at least it does not increase more than 12 mb)

rmtheis commented 7 years ago

at least it does not increase more than 12 mb

Yes, that's a positive sign. If there were some kind of memory leak I would expect the memory usage to continue to increase for this case as the test continues to run.

Do you know if the behavior you found of not immediately listing native memory as deallocated differs from that of other projects that run native code?

rmtheis commented 6 years ago

Thanks for taking a look at this and running the tests. There may be motivation for doing more testing here, but as this stands, I'm not convinced that this behavior reflects an actual problem in the code. Please open a new issue if you find out new information -- I'd love to see it.