[2.0.4] possible memory leak with long running scripts

Asked by Javier Gonzales Rodriguez on 2020-07-03

Hello there ...

Am using SikuliX for a basic gaming tasks, so .. the script is on a loop and it works fine during some hours, after that it stops and my OS (Linux mint 19.03) says that i run out of ram memory.

I read about memory leak and optimize my code to fix the issue, so i did it, now it takes more than 5GB (RAM) in like 10 hours running.

this is an example how i do my search:

CenterReg = Region(603,318,155,66)
swLocation = Location(159, 655)
GoldImg = "gold.png"

if centerReg.exists(GoldImg):
   click(swLocation)

My coding skills are very basics so, will be great if someone give me a recommendation.

More info:
What SikuliX version? 2.0.4
What system? Linux Mint 19.03
what Java? OpenJDK 64-Bit Server VM (build 11.0.7+10-post-Ubuntu-2ubuntu218.04, mixed mode, sharing)
Possible, to get your script? yes
Tesseract: tesseract 4.1.1-rc2-21-gf4ef
 leptonica-1.75.3
  libgif 5.1.4 : libjpeg 8d (libjpeg-turbo 1.5.2) : libpng 1.6.34 : libtiff 4.0.9 : zlib 1.2.11 : libwebp 0.6.1 : libopenjp2 2.3.0

 Found AVX2
 Found AVX
 Found FMA
 Found SSE
 Found libarchive 3.2.2 zlib/1.2.11 liblzma/5.2.2 bz2lib/1.0.6 liblz4/1.7.1

Regards!

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
2020-07-31
Last query:
2020-07-31
Last reply:
2020-07-30
RaiMan (raimund-hocke) said : #2

It seems, you still have the problem :-(

I have to admit, that I did not check for possible memory leaks since years now, because there have not been any complaints.

From your code snippet it is not possible to say anything about possible reasons.

But of course I am willing to look into it with low priority and no commitments, so it will take a while.

If you agree, send me your script (sikulix---at---outlook---dot---com).
Do I have a chance to test it live against the game on a Windows machine?

Hi Raiman,

yes, am agree, take a look if you can (no commitments), i will appreciate it.

On Windows is kind of hard because the anti cheat tools that they have but we can try it.

Thanks a lot Raiman.

Hi Raiman,

About this issue, I just found this...

Try this simple code:

ImgRegion = Region(542,235,232,204)
desktopImg = "desktopImg.png"
IconRegion = Region(1291,722,64,39) #choose a region with 4 different icons in there.
IconImg = "IconImg.png"
running = True

def stopScript(event):
    global running
    running = False

Env.addHotkey(Key.ESC, KeyModifier.CTRL, stopScript)

while running:
    try:
        if ImgRegion.exists(desktopImg):
            ImgRegion.click(Pattern(desktopImg))
            sleep(1)
        if IconRegion.exists(IconImg):
            IconRegion.click(Pattern(desktopImg))
            sleep(1)
        pass
    except:
        pass

- Stop the code and check your RAM, then change this:
IconImg = "IconImg.png" #choose an different image on the same IconRegion

- Run the code again and stop it, repeat the last step (change the image on the variable IconImg) and check your RAM.

So, basically Sikuli saves RAM for each image that found (reg.exists), in my real scenario am looking an image on a big region, the image is the same but it appears in different points inside of that region so, sikuli is taking it like a new img and is saving and saving RAM until I run out of RAM and it stops the script.

So my questions is ... if i have a loop, how I force to release the RAM where sikuli already saved matches before my next loop?

Note: If I close the SikuliX IDE, it release the RAM, that can be another solution but i rather to know how to do it inside a loop/function/etc

Thanks!

RaiMan (raimund-hocke) said : #5

I made some tests with VisualVM and that shows, that there is no permanent increase of memory consumption.

Java allocates a so called heap for application memory.
When an application runs, memory is allocated until this heap is nearly full.
Then Java's so called garbage collection frees memory from the heap, for objects, that are no longer in use (reference count 0).

So while a SikuliX script is running, the memory usage increases, until the garbage collection frees memory again.

Usually it is not necessary, to limit the heap size, since appropriate defaults are used.
But on systems with little memory it might make sense to do so.

here is a nice article about Java memory usage and control:
https://alvinalexander.com/blog/post/java/java-xmx-xms-memory-heap-size-control/

Hi Raiman,

Thanks for the information and your replies.

Based on the information that you provided me, i did these tests:

My PC has 16 GB of RAM (15 available), here is a screenshot of my capacity without running anything.
https://ibb.co/3m9tMd2

So, the next step was >> open the terminal and run this command "java -Xmx2g -jar sikulixide-2.0.4.jar ", it opened my Java JRE and I run my script.

This is the capacity on my PC running the script for the first time.
https://ibb.co/cDbq2XG

After 18 hours, these is the capacity of my PC.
https://ibb.co/CWSZFZw

i dont know why it is still consuming a lot of RAM, I have 2 scripts, one for "functions" and the other one that calls the functions that I need.

IMy import looks like this:
from sikuli.Sikuli import *
import functions

I mention this cause when i run my script, I need to load the" functions" script first (it saves some RAM) and then the main script where I import and call the functions, example:

function1()
sleep(1)
function2()

I tested running pieces of code from the functions manually, using the option "run selection" and it does the same (saves RAM almost every time that the loop find an image).

About your testing, which distribution did you tests?

I tested mint 19.03 and 20 (now) with the same results.

Do you have another recommendation?

Regards!

RaiMan (raimund-hocke) said : #7

Sorry, but I cannot help you in the moment.

Apparently the heap restriction to 2GB (-Xmx2g) is not respected in your situation.

I will set up my own longterm test and try to dig deeper.

Since such cases (searching for not-freed memory) are very hard and time consuming to evaluate, it will surely take some time.

I will make this situation a bug and you have to find a suitable workaround.

RaiMan (raimund-hocke) said : #8

Maybe this is a workaround helper for you:

- start the IDE normally and run your script in the IDE

- in $JAVA_HOME/bin there is a command jcmd

- in parallel to the running script run it in a terminal as $JAVA_HOME/bin/jcmd without any parameters and you will get the active JVMs

- find the pid for the JVM running org.sikuli.ide.SikulixIDE

- from time to time in the same terminal window run
   jcmd <IDE-PID> GC.run

This should run a garbage collection and the memory usage should be at a lower level afterwards.

I will use this utility to make my tests.

Best RaiMan (raimund-hocke) said : #9

... or you might trigger the garbage collection directly inside the script:

import java.lang.System as JSYS # at beginning of main script

JSYS.gc() # at loop start or loop end

... or somewhere else, where it makes sense.

Hi Raiman,

Again, thanks for the info, it seems like both options (I tested both for days) are helping to reduce the RAM consumption.

By the way, am using Java JRE 14.0.1, it works better than 11 for me.

Thanks for your support Raiman ...

Should I close this ticket?

Regards!

RaiMan (raimund-hocke) said : #11

Thanks for feedback.

The issue is now tracked here:
https://github.com/RaiMan/SikuliX1/issues/323

... so you can close this question.

Thanks RaiMan, that solved my question.