Forums

PlayOnLinux development: Behind the scene

Chapter I - SetupWindow synchronization

I'm just posting this message because I want to share some little tips and some mistake we have made while developing PlayOnLinux in the past. I will try to post as many as I can if I find any interesting topic.

Disclamer: If you are an advanced developer, you may find this post a little simplistic. Indeed it is highly simplified. Its intent is to try to untangle the design of PlayOnLinux 4 and to explain what solution we are using in PlayOnLinux 5.

Chapter I - SetupWindow synchronization

The main target of this post is to explain an anti-pattern that we've used in PlayOnLinux 4, and also how to avoid it.

Context

We you are using POL_SetupWindow_* commands, you are able to create some messages like this one:

POL_SetupWindow_message "Hello World!"

If you have only one comand, it is fine. However let see what's happening when you try to show two messages in a row.

The problem we want to solve in this topic is preventing the bash process to continue until the user has clicked on the next button. Otherwise, we would not have the time to see the first message.

We are going to assume that POL_SetupWindow_message is bound to a Python orJava message() method. We are not going to explain here the communication mechanism between bash and Python or between bash and Java, which is a different problem.

Let's take the following Python code:

message("message 1")
message("message 2")

The problem is: How can we wait for the user interaction before showing message number 2?

PlayOnLinux 4 approach: Busy waiting

This approach is an anti pattern. I'm just presenting it to explain why it should be avoided. To simplify the problem, we can assume that we have two differents threads in our program:

Thread 1 : Thread of the UI

Thread 2 : Thread of the script

The idea here is to block the thread 2 by creating a loop and periodically ask the UI if the user as clicked on the next button:

PlayOnLinux 5 approach: Use of signals

The PlayOnLinux 4 approach is not acceptable in terms of performance. Not only are we going to loose at least 200ms (in this example), but we are also uselessly wasting CPU time.

In PlayOnLinux 5, we are going to use the Semaphore object. A semaphore that has two methods: acquire (decrement) and release (increment). A semaphore cannot be negative. If a thread try to decrease a semaphore whose value is equal to 0, it will be blocked until another thread increments it.

Performance comparison

Now we need to prove that the new design is more efficient by doing some tests. We are going to test the POL_SetupWindow_wait command, because it does not need any user interaction. We are going to use the following scripts:

The idea is to count how long does it take to run POL_SetupWindow_wait 100, 500 and 1000 times.

Here are the result on my Laptop:

The difference is pretty amazing. We can observe that it takes about 10 minutes to execute POL_SetupWindow_wait 1000 times in PlayOnLinux 4 while it takes only few seconds with PlayOnLinux 5.

Conclusion

Of course, we will never find scripts that run POL_SetupWindow_wait 1000 times. But still, it is always a good practice to avoid losing performances when it is not necessary.

The fact that PlayOnLinux 5 is written in Java may also interfere with this benchmark. Ideally, we would need to make a fourth test to spot the differences of performances due to the choice of the language.

Also you can notice that POLv5 Python (Jython scripts) are way faster than POLv5 bash scripts. This difference will be explained in a next post, so stay tuned :)