multi-thread performance hit

Asked by Ador Juan Cruz

I've written a sikuli script to bot a game on bluestacks.
Its complete and it works great. Speed wise I optimize by using regions and I use timers to process the most common stuff and only process the less common stuff after x time has elapse.
I want to optimize it further and I was thinking of moving some of the non game related stuff like closing advertisements or an info popup etc which could happen at any point in the game onto a separate thread.
Question is will it affect the current performance of my script ? like image matching ?
basically I want to make my bot a little bit more faster by multi-threading.

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

Generally, you can expect your script to get faster with multithreading on a machine having more than one processor.

But Sikuli generally as such is not thread safe with respect to the generated objects like Screen, Region, Match, ... and updating their attributes.
So a thread should always have its own distinct set of objects (which is not trivial, when using the Python level: the "invisible" constant object SCREEN is used for all unqualified Region methods: click() is seen as SCREEN.click()).
So always use new (Region) objects in your threads (except in cases, where you exactly know, what you are doing).

The real problem with threading is the concurrent usage of mouse and keyboard: this is definitely not coordinated by Sikuli among threads.

So when using e.g. the mouse in a thread, this might interfere with its usage in the main or other threads.

The only way, to manage that is to build a queue of thread mouse actions, that are processed before the next mouse action in main, if the queue is not empty. the threads have to wait until their next mouse action is processed and removed from the queue.

The easiest way, to manage your situation with popups is to use
def popup1(e):
    # handle event e.g.
    e.region.click(e.match)
reg1.onAppear("popup1.png", popup1)
reg1.observe(FOREVER, background=True)

which will dispatch the observation and its handling to a thread.

But be aware: all the above aspects are still valid.

Revision history for this message
Ador Juan Cruz (ajuan7101) said :
#2

thank you for the quick reply.
I am running the bot on a quad core AMD machine so I if moving some of the load out of the main thread to another thread would make the bot faster, the better.
The queue would be the correct way of doing it. But since I only have 2 or 3 of these events I was thinking of just adding a global lock object to synchronize the mouse/keyboard use between the threads. Would locking any of the threads using lock.acquire/release cause any problems with sikuli ?
 Another question, while inside the event handler, the doc said it pauses the observe for that region but can I make a copy of the same region and do a region.exists/wait vanish calls inside the handler ?

Revision history for this message
Best RaiMan (raimund-hocke) said :
#3

--- lock.acquire/release
... should do the job, but that means, you have to make a wrapper around the mouse actions, so you do not need to frame every mouseaction with lock.acquire/release

--- can I make a copy of the same region
yes, it is only the specific region object, so inside the handler, this should do it:
newRegion = Region(event.region)

Revision history for this message
Ador Juan Cruz (ajuan7101) said :
#4

Thanks RaiMan, that solved my question.