-
February 13th, 2023, 15:46 #31
While I am very sympathetic with the concerns, if indeed it turns out to be a system problem with databasenodes degrading performance, the best thing for the community is in fact to bite the bullet and deprecate the problematic functionality. While worth avoiding wherever possible, this is a common reality for the maturation of any coding framework and necessary to retaining long-term viability. Performance of FGU is already a notable pain-point for many users and use-cases, and one that if left untended will inevitably result in FGU becoming noncompetitive in the VTT arena.
My Forge creations: https://forge.fantasygrounds.com/crafter/9/view-profile
My GitHub: https://github.com/MeAndUnique
Buy me a coffee: https://ko-fi.com/meandunique
Discord: MeAndUnique#6805
-
February 13th, 2023, 15:51 #32
Supreme Deity
- Join Date
- Mar 2007
- Posts
- 20,566
As MeAndUnique mentioned, the syntax for the strings is identical under the hood for Lua, but only for functions tied to a variable type. [vartype.fn(var, ...) == var:fn(...)]
Unfortunately, the whole point of this process is to make the databasenodes into very simple objects with no functions tied to them. If we don't have to register an entire global space to them, then that is a lot of overhead saved multiplied by the number of database nodes (hundreds of thousands or more per campaign with modules loaded). So, I can't just "hide" them in another calling method, or you still have all the overhead.
To be clear, if the performance is sufficient, this will be a planned under a year process with migration needed.
The migration is almost all a very straight regex replacement except for possibly nested calls, which are slow performance by themselves (i.e. multiple calls vs. single call).
Regards,
JPG
-
February 13th, 2023, 15:58 #33
Though to clarify, I wholly agree with the concept here if it is in anyway feasible. Taking it even a step further, any mechanism afforded by the Lua library FGU uses (or even one of the alternatives, being several candidates) that more closely aligns the object and memory management will itself yield numerous benefits to performance overall. As a simple example, the recent addition of a getChildList as an alternative to getChildren, if mapped to C# Dictionary-like synonyms would yield performance measures that differ only by passing a single additional reference, or in other words a handful of nanoseconds per loop. So considering the entire DB would still be way under a single second difference, complete noise in light of other performance concerns.
My Forge creations: https://forge.fantasygrounds.com/crafter/9/view-profile
My GitHub: https://github.com/MeAndUnique
Buy me a coffee: https://ko-fi.com/meandunique
Discord: MeAndUnique#6805
-
February 13th, 2023, 16:10 #34
- Join Date
- Jun 2020
- Posts
- 537
-
February 13th, 2023, 16:13 #35
- Join Date
- Jun 2020
- Posts
- 537
Yes, exactly.
Code:var lua = new Lua(); // Expose the databasenode userdata object to Lua var databasenode = new DatabaseNode(); // Create a Dictionary that wraps the databasenode methods var databasenodeWithMethods = new Dictionary<string, Delegate>(); databasenodeWithMethods["getValue"] = () => { databasenode.getValue(); }; databasenodeWithMethods["setValue"] = (string val) => { databasenode.setValue(val); }; databasenodeWithMethods["getPath"] = () => { databasenode.getPath(); }; lua["databasenode"] = databasenodeWithMethods;
The method calls on the `DatabaseNode` use an `XmlWrapper` class powered by C# `System.XML` and it each `DatabaseNode` just gets a pointer to the single instance maintained by the application using `xmlWrapper = XmlWrapper.Instance` which is one instance. This should achieve only one instance of the underlying XML Library needed by the application without having each database node instance instantiate their own.
I can provide more of what I did locally as a POC if it helps.
Edit: And yes in the above I was just printing within the methods instead of returning the values needed, but it's possible to wire it up properly.Last edited by seansps; February 13th, 2023 at 16:25. Reason: Code edit for clarity
-
February 13th, 2023, 16:13 #36
Supreme Deity
- Join Date
- Mar 2007
- Posts
- 20,566
On the string.fn(var, ...) vs. var:fn(...) part of the discussion; this approach with databasenode objects would not smooth migration any more than migrating to DB. That is because all the var.fn(...) calls with databasenode vars would need to be converted to either databasenode.fn(var, ...) or var:fn(...). Not really much savings in coding effort in that approach.
The current recommended change is DB.fn(var, ...). How is that different than the former conversion above?
Also, I think that the level of work that is being assumed with this change is higher than it is, I was able to convert about 20 rulesets in a couple days, including Core which is larger than most of the other rulesets.
Regards,
JPGLast edited by Moon Wizard; February 13th, 2023 at 16:16.
-
February 13th, 2023, 16:19 #37
- Join Date
- Jun 2020
- Posts
- 537
It’s not just converting the code, but also, the amount of time needed to do a full regression test of a ruleset to ensure no bugs get into production.
Additionally, all the extensions that would need conversion as well.
In any case, check my response above — there’s a way to maintain “.” Notation functionality and not embed the API into each userdata object.
-
February 13th, 2023, 16:53 #38
Supreme Deity
- Join Date
- Mar 2007
- Posts
- 20,566
Actually, there is not a way to maintain a dot notation in Lua without embedding the API into each object. The way that Lua works is that the dot notation is a Lua table lookup, so that name = fn entry must exist in the object in order for var.fn(...) to work.
As mentioned above, adding a "databasenode" "library" to support databasenode.fn(var, ...) or var:fn(...), is not that different than DB.fn(var, ...). The example you displayed above just creates a "databasenode library".
Regards,
JPG
-
February 13th, 2023, 17:12 #39
- Join Date
- Jun 2020
- Posts
- 537
I see, how about this?
Code:using System; using System.Xml; using NLua; class Program { static void Main(string[] args) { var lua = new Lua(); // Expose the databasenode userdata object to Lua var databasenode = new DatabaseNode(); lua["databasenode"] = databasenode; // Run the Lua script lua.DoFile("script.lua"); } } class DatabaseNode { private XmlWrapper xmlWrapper; private XmlNode nodeElement; public DatabaseNode() { xmlWrapper = XmlWrapper.Instance; var xmlDoc = xmlWrapper.LoadXmlFile("database.xml"); var children = xmlDoc.GetElementsByTagName("charsheet"); nodeElement = children.Count > 0 ? children.Item(0) : null; getValue = this.GetValue; setValue = this.SetValue; getPath = this.GetPath; } public Delegate getValue; public Delegate setValue; public Delegate getPath; public string GetValue() { return nodeElement.InnerText; } public string SetValue(string value) { // TODO return "SET TO " + value; ; } public string GetPath() { return "database.xml"; } public void GetChild() { Console.WriteLine("TODO"); } public void GetChildren() { Console.WriteLine("TODO"); } /// ... etc, other methods needed for DB Node }
-
February 13th, 2023, 17:17 #40
Supreme Deity
- Join Date
- Mar 2007
- Posts
- 20,566
You're still assigning this library of functions to "databasenode" as a variable. It's all the same thing you're hashing over.
Regards,
JPG
Thread Information
Users Browsing this Thread
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks