Performance Problems

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Performance Problems

Post by rozek » Wed Dec 19, 2007 7:33 am

Good morning!

After some surprising performance problems with a really simple Revolution script (Revolution Studio 2.8.1, Build 472 under WinXP, Core Duo 1.66 GHz, 1GB RAM) I decided to do some basic performance measurements. Here is the script

Code: Select all

lock screen
  local firstTime,lastTime
  put Milliseconds() into firstTime
    create invisible field "(TestField)"

    repeat 2000 times
      put ("12345678901234567890" & return) after field "(TestField)"
    end repeat

    delete field "(TestField)"
  put Milliseconds() into lastTime
unlock screen

put "populating the field took " & (lastTime-firstTime) & " milliseconds"
Running the loop 1000 times (instead of 2000 as shown above) took 500...550 milliseconds, running it 2000 times took 4000...4600 milliseconds, when I tried to run it 10000 times I had to abort the program using the task manager...

I also tried with "Debug Script Mode" switched off - which sped up the program only a little bit.

All measurements were made within the Revolution Studio IDE, not for a stand-alone program. The IDE was started immediately before - I therefore do not expect any other messages or stacks "in the background"

I can't believe such a poor performance: 21*10000 characters are "nothing" for today's systems. Thus, I think of a mistake on my side.

Does anybody have any idea?

Thanks in advance for any hints!
Kind regards,

Andreas Rozek

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 7:44 am

Hmmm...

when I use a local variable and populate that instead of the field, the loop (with 2000 iterations) terminates after 4 milliseconds - and the one with 10000 iterations after 9.

Thus, it seems that GUI functions are (terribly) slow.

As I plan to write a specialized editor which should be able to deal even with text sizes of 10MB the question arises: what is the recommended way to deal with controls (especially fields) without running into performance problems?

The "text" will contain lots of "decorations" (LinkTexts et al.), and the operations on the text will include the (interactive) removal and insertion of character sequences within the text.

Setting the (html)text of a field will presumably require to reparse the whole text - therefore I hoped that the insertion of new text into an existing one would perform better.

Are there any hints how to guarantee performance?
Kind regards,

Andreas Rozek

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 7:53 am

Just some additional remarks:

- with 100000 iterations the loop took 160 ms
- with 1000000 iterations it terminated after 16500 ms

Reason: despite 1 GB RAM and a freshly started WinXP, the system had to use swap space(!!!!)

Revolution itself consumes 36 MBytes before starting the script and consumes up to 103 MBytes during the loop. Thus, 67MB are used for 21MB text plus Garbage Collection (which, in my opinion, is still no reason for the system to swap - but, well, Microsoft and resources, we all know that topic...).

Is there a way to inform Revolution about the foreseen size of a variable (similar to the StringBuffer of Java)? Otherwise, with many iterations, my loop test becomes a test of Memory Management and Garbage Collection...
Kind regards,

Andreas Rozek

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 8:49 am

Some more numbers and results

(in order to better compare them)

Without the possibility to preallocate space for a variable which is to be filled the following operations might have to be performed (in the worst case)

- allocate new memory for the (extended) variable
- copy the old contents to the new memory
- copy the additional contents to the new memory as well
- release the old memory

In a loop with 1000000 iterations (21 bytes each) this would mean to copy 1*21+2*21+...+999999*21 bytes in total (= (1+2+...+999999)*21 = (999999*1000000)/2 = 499.999.500.000 = 500GB) Puh, 500GB in 16 seconds? not bad ;-) Well, in reality, I guess, Revolution might do without many of the copy operations because of smarter memory (re)allocation...

(Edit: oops, I forgot the factor of 21 bytes in my calculation - in fact, we are talking about (theoretically) having to copy approx. 10 Terabytes ;-) is my calculation correct now?)

On another machine (with WinXP, 512MB, Pentium M 1.6 GHz, but better optimized WinXP settings)

- the revolution loop with 1.000.000 iterations tooks 9500 ms
- I had to abort another script writtin with AutoIt (the loop with 10000 iterations already took 3.7 seconds - they really seem to copy the old variable contents!)
- I also had to abort a Lua script (the loop with 30000 iterations already took 25 seconds - again, they seem to copy)

Thus, the pure script performance of Revolution (i.e., when using variables) does not seem too bad! Now, I have to learn how to use fields efficiently!
Last edited by rozek on Wed Dec 19, 2007 9:59 am, edited 5 times in total.
Kind regards,

Andreas Rozek

Klaus
Posts: 13878
Joined: Sat Apr 08, 2006 8:41 am
Location: Germany
Contact:

Post by Klaus » Wed Dec 19, 2007 9:26 am

Hi Andreas,

did you try to put everything into a variable first and then put it into the field "en bloc"?
That might speed up things a bit...


Regards and Grüsse

Klaus

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 9:51 am

Hello Klaus,

sure - using variables performs much better - this is what I already found out.

But what happens, if I want to modify a small slice within a long (field) text? Will I have to

- copy the field contents into a local variable (doubles space requirements)
- modify the local variable (here Revolution uses some pretty intelligent memory allocation optimizations, as I have seen)
- set the field contents to the new contents of the variable (requires reparsing and formatting of the whole text)

or are fields intelligent enough to reformat themselves only from the beginning of the modification on?

Due to their (albeit limited) HTML capabilities, fields are probably the most versatile GUI control of revolution (I'm currently using them to implement hierarchical tree view with expandable and collapsable nodes)

Of course, this assumption might already be (terribly?) wrong - thus, if anybody has a better idea, please tell me!
Kind regards,

Andreas Rozek

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Wed Dec 19, 2007 11:01 am

Hi Rozek,

I too have had some trouble with Revolution eating memory. Usually, this is due to an excessive use of controls one way or another.

If I run your script putting the data into a variable, I need 4 milliseconds for 2000 loops. That seems a good performance to me.

Best,

Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 12:19 pm

Hello Mark!

Thanks for your response!

I don't worry about the performance when dealing with variables (indeed, there are many other scripting languages which have to give up even below 100.000 iterations, not talking about the 1.000.000(!) iterations which Revolution dealt with really fast (9...16 seconds roughly))

My problem is:

- sooner or later I have to deal with a field
- the contents of this field may be large and will have to be modified interactively
- doing so in the naive way might consume lots of resources

What is the "expert approach" to modify the contents of a field? get-modify-set consumes RAM and requires the field to reparse the whole(!) text upon even the slightest modification. In-situ-modifications (within the field itself) seem to be slow as well (indeed, this was the reason why I looked at the performance with more detail) Is there a third way I am missing right now?
Last edited by rozek on Wed Dec 19, 2007 1:36 pm, edited 1 time in total.
Kind regards,

Andreas Rozek

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Wed Dec 19, 2007 12:26 pm

Hi Andreas,

Yes, I often put data from a field into a variable before pocessing data.

I never need to put that much data into a field, though, and believe that the "third way" is to restructure your data and distribute it among multiple fields.

Best,

Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Wed Dec 19, 2007 1:07 pm

Hello Mark!

Thanks for your quick response.

Unfortunately, I'm away from my desktop right now - thus, I can't really test and measure the performance of several code variants. However, I don't think I can distribute my "text" among several fields as my next "problem" will be to implement the hierarchical list view I mentioned above. The number of entries (i.e. field lines) may grow up to several thousands, at least, each with an icon, a title of arbitrary length and the usual indentation overhead. The title should be interactively modifyable, and expanding/collapsing a node should not take too long.

Some languages/runtime environments solve the problem of scalability by keeping the underlying data in a separate table and rendering only those items which are actually visible - forgetting about the majority which is not shown anyway. (or some other approach based on callbacks into the application etc.)

Under Revolution, I have the impression that I'll have to provide the HTMLtext for all lines at once, regardless whether they are visible or not. This is what makes me worrying about performance.

Or is there an alternate approach I don't know yet?
Kind regards,

Andreas Rozek

BvG
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1236
Joined: Sat Apr 08, 2006 1:10 pm
Location: Zurich
Contact:

Post by BvG » Wed Dec 19, 2007 4:05 pm

Fields are really the slowest place to set textual data, everything else is faster.

Said that, you could make what you suggested yourself: keeping the data in a variable, only showing parts (+ some beyond the borders) that are currently visible in the field. This will most likely reduce scrolling speed, so this is ideal for cases where you do not allow scrolling at all.

Mark already mentioned that distributing your text among several fields will be often faster.

If that's not enough speed for you, then use C or assembler, because unlike Rev, these give you full control about how fast your code should run.
Various teststacks and stuff:
http://bjoernke.com

Chat with other RunRev developers:
chat.freenode.net:6666 #livecode

Mark
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 5150
Joined: Thu Feb 23, 2006 9:24 pm
Contact:

Post by Mark » Wed Dec 19, 2007 4:38 pm

Rozek,

If you are using a hierarchical list, I bet you don't need to put all thousands of entries into the field. You only need to show all main category and 1 category that is folded open and that is why I believe you can limit the amount of data in the field.

Best,

Mark
The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

rozek
Posts: 151
Joined: Mon Jun 19, 2006 2:29 pm
Location: Böblingen, Germany
Contact:

Post by rozek » Thu Dec 20, 2007 9:33 pm

Hello!

I'm a bit low on time, but nevertheless:

- using something else than Revolution for basic operations would not really be an option (hey, I've chosen Revolution for NOT having to use C ;-) )
- even a hierarchical list with collapsible nodes should still react immediately when all nodes have been expanded
- users have certain expectations when using today's software - and one of them is scalability (hey, my mailer currently manages thousands of emails without really getting slower - I would immediately throw it away otherwise!)

And, well, it seems as if this requirement can be met with Revolution itself!

Here are the results of my (very first) experiments:
- complicated lists (or their HTML representation, resp.) may be efficiently constructed "off-screen" using local variables (Revolution has shown a really impressive performance in that area!). The result of that construction may then be assigned to a field
- sole modifications (e.g., the insertion/modification/deletion of a single line or a few consecutive lines are best done directly within the field itself
- more complicated modifications are better done "off-screen" and then inserted into the field in a single operation

I'm still experimenting (e.g., I want the scrolling position to behave "as one would expect").

Currently, however, it looks as if it would be relatively straightforward to write (relatively) scalable applications with Revolution.

Just as a note: I'm currently testing with 100.000 lines in a single field, that's ok for the moment ;-)
Kind regards,

Andreas Rozek

Post Reply

Return to “Talking LiveCode”