|
|
|
In past 2.x versions of CMUD, string lists and database variables (tables) could be used to store some structured data, but their use was limited. You could create a simple string list, such as:
list = {item1|item2|item3}
or you could create a simple database variable such as:
db = {name=Zugg|level=20}
but if you tried to mix these two, such as placing a string list within a database variable, all sorts of problems would emerge. Even when it worked, CMUD v2 could not use it's internal hashing to speed up a string list that was stored within a database variable, resulting in slow operations.
In v3, the string list and database variable code has been rewritten to allow any level of nesting and to have high performance at all times. String lists and tables are stored internally as JSON data structures, similar to the data structures used in Lua and Javascript.
Nesting arrays and tables
The proper method for nesting an array within a table (or vise-versa) is the same as it was in v2. Using the above two variables, you could add the @list string list to the database variable using the #ADDKEY command:
#ADDKEY db list @list
Now if you access @db.list you will get the {item1|item2|item3} list. While this seemed to work in v2, it was really only returning the actual *string* value of "{item1|item2|item3}". v2 did not allow you to query an item within this list directly. In v3, the actual string list structure is returned, allowing you to access the list items directly with this simple syntax:
#SHOW @db.list.2
to display "item2", which is the second item in the list. This "dot notation" can be used to access any part of a nested table or array to any levels deep. And high performance caching it used at each level for maximum speed.
String formats
If you use the existing list commands and functions, such as #ADDITEM, #ADDKEY, etc, then you will have no problem using these new enhancements in your script. However, if you are relying upon the "string format" of a list or database variable, then you might have problems.
For example, some people create a string list using %concat to form the string, such as:
list = %concat("{","item1","|","item2","}")
or variations of the above syntax. Using %concat in this way will create @list as a string variable and not as a stringlist. You can convert a string variable to a proper list using the new %list function. CMUD will also attempt to handle the string variable properly, such as when accessing an element like @list.2. But because CMUD must internally convert the string value to a list this is much less efficient than creating a proper string list in the first place. Needless conversions between string format and internal json format will be the biggest causes of slow scripts.
So be sure to convert your scripts to remove any dependence upon the actual string format of the list or table. Use the provided commands and functions to add items to the list, or change items in a list, or delete items, etc.
Raw JSON data
You can convert a string list or database variable into a JSON string format using the new %json function. Normally this function is for debugging purposes. The JSON string format is also displayed when you use the #VAR command to dump the variable, or when you export the variable to XML.
If you are using a web-related script to retrieve data from a web service in JSON format, you can convert that json string value into a proper list or table also using the %json function.
For backwards compatibility, but the JSON string format and the original CMUD stringlist or database variable string format is saved in your package and exported via XML. This allows your package file to still be read by the older v2 CMUD. In the future when fewer people are still using v2, this option will be removed so only JSON data will be stored in your package. In the meantime, if you have very large lists or tables, your data will be doubled in the package. If you don't plan to use CMUD v2 anymore, you can turn off this compatibility option in your Scripting Preferences "Output compatible string lists" option.
Performance
The new list/table format is very efficient, even compared to the hashing algorithm used in CMUD v2. Here are some benchmark comparisons. Click Here to see the actual test scripts.
CMUD v3
Code: |
Arg: 100 1000 10000
-----------------------------------
makelist 2 19 189
makedb 2 23 225
querylist(100) 1 16 155
querylist(10000) 1 16 159
querydb(100) 1 16 155
querydb(10000) 1 15 153 |
To explain this chart, there are different test scripts (like "makelist"). The number across the top is the argument to send to the script alias. The cases with the number in parenthesis, like (100) indicates the size of the list/table was used to perform the script. All times are in milliseconds.
For example, the "querylist(10000)" test was run by first creating a list with 10000 elements (makelist 10000) and then each column is a different argument to querylist, such as "querylist 100" for the second column result.
The above table shows that the time to create and search both lists and tables scales linearly with the argument. Searching for 1000 items takes 10 times longer than searching for 100 items. However, this search speed does NOT depend upon the size of the list being searched.
Compare the nice results show above with the same tests performed in CMUD v2.37:
CMUD v2.37
Code: |
Arg: 100 1000 10000
-----------------------------------
makelist 5 374 36685
makedb 2 20 200
querylist(100) 4 49 508
querylist(10000) 3 194 18426
querydb(100) 2 69 775
querydb(10000) 1 15 164 |
Notice that all of the times are longer. Also notice that the scaling is not linear, especially for string lists which are quite inefficient. Creating a string list with 10,000 elements took over 36 seconds! Compared to 0.2 seconds in CMUD v3.
Also notice the large difference in times depending upon the size of the list. Searching for 1000 items in a small list took 49ms but searching for 1000 items in a large list took 194ms.
Finally, notice that searching a small db table actually takes longer than searching a larger table because of how hash collisions were handled in v2.37.
Just for amusement, the same tests can be run in zMUD.
zMUD v7.21
Code: |
Arg: 100 1000 10000
-----------------------------------
makelist 9 368 35643
makedb 14 1100 114966
querylist(100) 9 106 1078
querylist(10000) 64 863 33833
querydb(100) 10 124 1274
querydb(10000) 124 1552 48770 |
These results show that anybody still using zMUD for scripts containing string lists or database variables will have very slow results! |
|