Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Wed Jun 09, 2010 5:03 pm   

Breakthrough for v3.19!!
 
I guess the backwards compatibility "pain" that I talked about in the other thread had a reason. This morning I had a real performance breakthrough with the CMUD code.

Remember the old "NoSave" flag for variables? The idea was to prevent a variable from being saved to the database for higher performance. This option is set for variables that have the "Use Default" flag.

There are really two databases in CMUD. There is the external *.PKG database, then there is an internal database used to store your settings. The speed increase from the NoSave flag is really from the *internal* database. The external database is saved in a background thread and only runs every 30 seconds or so. So the external database isn't really a performance issue. But with the internal database, the new value of a variable is saved whenever the variable changes. So setting the NoSave flag prevents this and increases the speed of assigning values to variables.

With string lists and database variables, I was also bypassing the internal database storage to prevent the hash tables from being converted to a string (the internal SQL database can only store string values). The string format of a hash table was only computed when the *external* pkg database was being saved. So string lists and database variables were essentially acting as "NoSave" variables already.

Here is the breakthrough: If string lists and database variables can bypass the internal database saving, then what about all other variables? Why can't *every* variable bypass the internal table and only be saved to the external database?

What kind of speed benefit can this give? Depends upon the script. But let's just look at variable assignment directly. Here are two test scripts:
Code:
#ALIAS testsave {a="";$start=%secs;#LOOP %1 {a=%random(1000)};#SHOW (%secs-$start)}
#ALIAS testnosave {b="";#NOSAVE b;$start=%secs;#LOOP %1 {b=%random(1000)};#SHOW (%secs-$start)}

The first alias saves random values to @a normally. The second alias saves random values to @b with the #NOSAVE flag set. When I run this on my system, for a loop value of 10000 I get a speed of "403" for the first alias and "134" for the second alias. So variable assignment is about a factor of two faster with #NOSAVE set.

This is the speed increase that you'll get in v3.19 for ALL variables. The #NOSAVE flag is going away. All variables will still get updated to the external package file, but all variables will bypass the internal database just like using nosave. You'll probably only see a small speed improvement to your scripts since you are usually doing a lot more than plain variable assignment. But any speed increase like this is good.

For hard-core programmers, the reason saving the value to the internal database is relatively slow is because the database "Value" field is a "Memo" field because variables can have values longer than 255 characters. Databases cannot optimize Memo fields like normal short string fields because so much memory allocation is needed to deal with large values of unknown size.
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Wed Jun 09, 2010 5:23 pm   
 
Oh, for better speed comparison, I forgot something. If I just use this script to test the raw speed of the loop itself:
Code:
#ALIAS testnone {$start=%secs;#LOOP %1 {#CALL %random(1000)};#SHOW (%secs-$start)}

then I get a speed of "104". So this value needs to be subtracted from the above results to get the actual speed of the variable assignment. That means the "testsave" is really (403-104) = 299, and the NoSave test is (134-104)=30. This shows the speed increase to be more like a factor of 10 than just a factor of two for raw variable assignments.

Also came across something interesting with this. If you change the #CALL to #NOOP you get a speed of "1308". Why is #NOOP so much slower than #CALL? Because in zMUD some people were using #NOOP to call COM-based stuff. So in CMUD, the argument to #NOOP is actually compiled (like doing %eval). So that will give people an idea of how much slower it is to run a pre-compiled script (#CALL) vs compiling at runtime like %eval (#NOOP). It's a pretty big speed increase.
Reply with quote
GeneralStonewall
Magician


Joined: 02 Feb 2004
Posts: 364
Location: USA

PostPosted: Wed Jun 09, 2010 7:19 pm   
 
I'm a bit confused by this 'So that will give people an idea of how much slower it is to run a pre-compiled script (#CALL) vs compiling at runtime like %eval (#NOOP).' I assume you meant faster instead of slower? Just want to be clear so I can change my scripts to use one or the other.
Reply with quote
Arminas
Wizard


Joined: 11 Jul 2002
Posts: 1265
Location: USA

PostPosted: Wed Jun 09, 2010 7:48 pm   
 
#call is the fast one.
#noop re-compiles each time it is run.
_________________
Arminas, The Invisible horseman
Windows 7 Pro 32 bit
AMD 64 X2 2.51 Dual Core, 2 GB of Ram
Reply with quote
Taz
GURU


Joined: 28 Sep 2000
Posts: 1395
Location: United Kingdom

PostPosted: Wed Jun 09, 2010 8:24 pm   
 
I attempted to add a strikethrough on slower so I could then append faster but neither [s] nor [strike] work.
_________________
Taz :)
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Wed Jun 09, 2010 10:28 pm   
 
Yes, what Arminas said. Sorry for the typo.
Reply with quote
Tech
GURU


Joined: 18 Oct 2000
Posts: 2733
Location: Atlanta, USA

PostPosted: Thu Jun 10, 2010 4:54 pm   
 
So does this mean you'll be doing away with the internal database altogether? If none of the variables will update it how will it be used? Will it be synched with the external database at save time? Just curious as to the implications.

Kudos on wringing out even more speed improvements.
_________________
Asati di tempari!
Reply with quote
MattLofton
GURU


Joined: 23 Dec 2000
Posts: 4834
Location: USA

PostPosted: Thu Jun 10, 2010 7:29 pm   
 
Essentially (assuming I understood him correctly), he's converting variables from a "settings" perspective to a "mapper room" perspective. Settings (ie, triggers, aliases, etc) are created/modified in the internal database to take advantage of the faster RAM speeds. At a predetermined interval, the internal DB is then applied to the .pkg file, so if something happens to your computer prior to this interval event then you lose the new data. However, mapper rooms are written straight to the .dbm file on creation so there's no "save lag". What you see on-screen is what is actually in the .dbm mapfile.

The internal DB will still very much exist, there just won't be any variables in it anymore.
_________________
EDIT: I didn't like my old signature
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Thu Jun 10, 2010 10:19 pm   
 
Quote:
So does this mean you'll be doing away with the internal database altogether?

Oh, definitely not. The internal database is extremely important for data integrity and is a core part of the CMUD architecture. All I've done is bypassed this layer when storing variable values to avoid creating the string format of tables/lists un-necessarily.

What I'm doing is really a huge "no-no" in proper computer programming. Normally when you implement layers of an architecture, each layer only talks to the next layer through a well-defined interface. You are not supposed to allow layers to look inside the internals of some other layer.

In the design of CMUD, the architecture was set up so that the settings are accessible via standard Delphi dataset structures. Outside of this, no other CMUD modules would need to know how the actual settings were stored internally. This allows the background thread that updates the *.PKG file to just check to see which records of the internal database have been modified and then create the proper SQL statements to update the external database file.

Over the years, this strict database interface has been broken a few times. In the early days of CMUD, the Package Editor was a "pure database editor". The package editor didn't know anything about the internal structure of settings, it was just editing the exposed database interface for the settings. Remember the database-aware TreeView that CMUD used to use in the Settings Editor? It was horribly slow. Any change to the database would cause it to want to update itself and re-read the entire database. It was a mess. So back then I broken the strict architecture and allowed the settings editor to exist *below* the internal database layer so that it could directly access setting structure. Then the package editor was rewritten to not use the internal database at all, giving big performance boosts, but at the cost of modularity since now the package editor depends upon the specific internal storage of settings.

So now I'm just breaking this interface rule again for performance reasons.

Is there still a real reason for the internal database anymore? Yes, I still think it helps with data integrity. It isolates the external PKG database from possible memory corruption in the internal settings structure. Otherwise we'd be back in the same boat as zMUD with corrupted settings. The fact that I break this rule for table/list variables means that they might be more susceptible to data corruption. If anything happens to the internal json table structure, then it's possible for garbage to be written to that database field. But that still won't cause other settings to get corrupted, so it's still worth having the database.

Matt isn't quite correct either. I'm not using a "mapper room" perspective. There is still a disconnect between variables and the external *.PKG database. You are correct that with mapper rooms, they are directly tied to the external *.dbm database and changes are updated in the database immediately. This gives no "save lag" but makes mapper updates extremely slow. For the mapper, this kind of performance decrease isn't very noticeable.

But for variables, if the external database was updated every time a variable changed value, then scripts would be very slow. Updating the external database is slower than updating the internal in-memory database (which is why the external database is updated in a background thread).

So yes, variables are no longer updated in the internal database. The records in the database exist, and the name and option fields are still stored there (in fast string or integer fields), but the *value* of a variable is no longer stored there (because it's a slow memo field)

The value of other settings (aliases, triggers, etc) are still stored in the internal database because these kind of settings just are not updated as often as variables. So they wouldn't really benefit much from a speed boost like this.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net