September 2019 Archives

Circular observations

Selfies demonstrate one of the principal laws of physics, psychosocial development of teenagers and programming. The act of observation alters that which is being observed. It becomes more complicated if the observer is observing itself. As the observer changes, so might future observations particularly if the tool being used is known to impact the parameter that is being measured; rapidly one loses hope that any meaningful data will be obtained from such a direction of development. Sounds gibberish? Look at the collection of "duckfaces" on your teenage daughter's phone (if she ever lets you near it) and I am sure you will find no resemblance of those images to anyone you would recognise as your offspring.

Let's do it any way

It is so with programming. But let's not let that stop us from still trying eh? The problem I alluded to in my last blog post regarding memory leaks in some GUI back ends offers such an opportunity. I had observed these leaks when trying to use timers to do animations. The way these animations were created was by creating a simple svg file, and altering that file in Perl, saving it, and inserting that file into an image panel, and repeating. A slowdown was noted with some back-ends , and using top, one can see the memory being consumed by that Perl interpreter process progressively rising.

I want to automate this measurement, and visualise the output graphically. But I don't know the pid of the process until I start the application. But my application knows its own pid. And my application itself can generate graphics. It can measure how much memory it uses, storing the data captured in an expanding data structure (an array) using changing amounts of memory, and using a subroutine that takes time and memory itself. It can then generate an SVG chart which gets more data points added each cycle, saving it and reloading it using processes that itself are suspect in memory leaks, and finally rendering this graph on the leaky UI. A fun-filled fool's errand that may deliberately exaggerate leaks thus demonstrating and identifying problematic systems while not, at first glance, offering fine grained analysis.

The pmap <options> <pid> system command (Linux).

$$ in Perl gives us the Process ID. Passing this as a parameter to pmap delivers a running application's memory footprint. It not only describes the total memory it uses but also subdivides the amount by internal structures which may give more clues as to what may be hungry for RAM. We can (for now) discard all the extraneous data and focus on the last line of the output (containing the total memory used) and progressively generate a chart of the excess memory being used with each cycle within the application and deliver it to the image panel widget in the UI.

 sub memRequired{
     my $mr=`pmap $$`;             # call pmap
     $mr=(split('\n',$mr))[-1];    # get last line
     $mr=~s/[^\d]//g;              # just keep numeric portion
     return 1*$mr;
 }

Keeping an eye on the ball

qt Chart.pngThe animation script from before is now modified to allow selection of which animation is being done. The animation may be stopped without stopping the timer, and It is also possible to overlay the chart on top of the other SVG animations already playing. So I have done a couple of simple tests. It is clear it is not the timer objects themselves that are directly involved in the memory leak. It is the Image panel update process. Tk and Wx need ImageMagick...but Tk leaks more than Wx. In these tests Qt appears the leakiest (Figure 1) although not obviously using ImageMagick.

GT3 Chart.pngGTK3 and GTK2 both lose no extra memory with SVG animations generally. The slideshow (jpg images once updated every second) appears to show transient extra memory used, going up in step wise fashion, as if dependent on the size of the image displayed (Figure 2).

Tk Chart.pngFor the backends that do use memory while playing SVG images there appears to be a consistent amounts of memory lost each time. The images have varying complexities, but this seems not to matter...all the svg images are 200px vs 200px. Most animations in these tests update 10 times per second, but clock and the slide show updates the frame once a second. Switching between the 1/10 sec and 1 sec produces a predictable patterns of memory leak.

I would like to see if there are other ways to put an image into a frame other than using Image::Magick. ImageMAgick does support a huge number of formats though. I would prefer to be able to migrate to Imager. This seems more tightly integratable into Perl.

Re-Entry of GUIDeFATE into CPAN

Any way the timer handling is now more or less uniformly supported across Gtk2, Gtk3, Qt, Wx and Tk. I would not use it for animations in anything other than using the Gtk2/3 options. GUIDeFATE for almost the last year has been not synced with CPAN. Version 0.13 will see it back on GitHub but with some changes. I will be removing the sub-modules from the base path into a folder of its own, so GFTk becomes GUIDeFATE::GFTk, starting 1st October. The latest version on GitHub will also be updated roughly at the same time.

Time Flies, Memories leak...GUIDeFATE getting a timer

It appears that I have not had single blog post for 1 whole year. Let's face it, there isn't enough time in the day to everything one might want to do. Procrastination steals more than just time though. The longer one is away from a particular activity the more difficult it is to return to that activity physically or intellectually. Some of you will recall that I developed what I claimed to be the world's simplest GUI designer, GUIDeFATE. This was the topic of a couple of presentations already but as all such projects, remains in a state of flux.

One key component of a GUI is a continuous loop that keeps monitoring human interactions and responding to this by updating the interface. What if we wanted the interface to update continuously, like a monitor, without a connection with a human input trigger? It is certainly not possible, for example to create an animation by just doing foreach(1..$x){sleep $interval; updateImage();}. This merely blocks the GUI mainloop, until the loop is completed with the display updating only after the loop completes and the control goes back to the GUI's mainloop. Instead one needs an event monitor, and more specifically a timer. The ideal scenario may have been to use something like AnyEvent or Ev, but sadly this can not be applied to all the backends; at least I do not know how one might do this. What follows is my usual trawl through the internet to source examples of timers in GUI applications with each of the various backends.

Plug-in Timer

I discovered that Tk and Gtk can work with AnyEvent/AE fairly easily. Qt and Wx have their own way to create timers. While Qt seems to be supported in the documentation for Any::Event, the general recommendation appears to be not to use Qt. Qt Slots have to be predefined and can not be made on the fly. A little jiggery pokery and we have a simple way to abstract timers through multiple back ends. BUT all is not as straightforward as one would like, as I discovered when trying test animations in various backends.

To abstract the timer in the various supported back-ends, Gtk3, Gtk2 (thanks chanio), Qt4, Wx from the UI string requires a single line added to the textual representation of the UI e.g.

my $window=<<END;
+--------------------------+
|T Animation               |
+--------------------------+
| +I--------------------+  |
| | clock.svg           |  |
| |                     |  |
| |                     |  |
| |                     |  |
| |                     |  |
| |                     |  |
| +---------------------+  |
|                          |
+--------------------------+

timer 100 ecg 1

END

GUIDeFATE detects the timer line, and in the case above, executes the subroutine "ecg" every 100 milliseconds. Any::Event (gtk or Tk) or Wx will happily accept a callback function reference from a string...e.g. \&{"main::$functionName"}, Qt needs a predefined callback subroutine as a slot. While this subroutine could then be used to jump to the desired subroutine, there is some inflexibility in that the number of timers that one could create are limited.

Testing timers.

I figured the best visual way to test a continuous timer would be to make a slide show updating an image window; or perhaps using a image that is updated to make an animation. The easily portable way to make an animation in Perl (without added dependencies) I figured, would be to make SVG images with only minor textual changes (something Perl is good at) required to make a graphical change. Here is GUIDeFATE being used in an application running 4 different animations made by continuously redrawing an SVG file and loading the recreated image into a frame.

Animations

When I tested the timers for such animations I found 1) that Wx, Tk and Qt applications progressively used bigger and bigger amounts of memory, with Wx particularly slowing down to a stand-still after a few hundred timer loops 2) Gtk and Gtk2 seemed to use much the same amount of memory regardless of how long it ran for. Now Tk and Wx both used Image magick to put the images into the image panel. Could this be the cause? more testing is necessary.

Things to do

GUIDeFATE 0.13 is not yet on Github or CPAN...I need to sort a few things out first.

1) One of my targets is to restructure GUIDeFATE distribution so that it does not pollute the namespace as much as it does now. I would like to move the back end modules so that they are not in the root names space e.g. GUIDeFATE::GFWx. Before that (I think) I need to wipe the old GUIDeFATE from CPAN...not sure how to to do that without creating havoc.

2) I need a few methods to delete timers, change intervals, or the callback functions...should be easy, but need to to choose methods that will be easy, and of course test them.

3) I need to test on non-Linux machines...I have no Windows PCs or Macs.

Hopefully will have this ready by the next Perl Meeting, who knows?

About Saif

user-pic An Orthopaedic Surgeon, A Tissue Engineering Scientist, Lecturer, (and Hobbyist Programmer, Electronics Engineer and Roboticist)