
Hi, I've been trying to help someone debug a performance problem ("Possible infinite loop detected") with the 5eShapedCompanion script. The GM in question has a rather large campaign - he's created characters for most of the entries in the Monster Manual + loads of extra NPCs + PCs from various campaigns + spell templates + a bunch of stuff from various WotC adventure paths. In total he has 750 character objects in the campaign. Now I know this is not entirely advisable - and I've recommended that he takes an alternative approach - but in the grand scheme of computer programming, it's not such a huge amount of data to work with, and it really ought not to result in things timing out > 30seconds. So I decided to do a bit of debugging, on the assumption that I'd probably done something a bit daft in the script somewhere. But after a bit of digging, I couldn't find any smoking guns in my script, so I did a little bit of very simplistic profiling of a basic test case: on('chat:message', (msg) => {
if(msg.type === 'api' && msg.content === '!test') {
const start = Date.now();
const profile = [];
createObj('character', {name:'TestingChar'});
profile.push({name:'charCreated', time:Date.now()});
const char = findObjs({type:'character', name:'TestingChar'})[0];
profile.push({name:'charRetrieved', time:Date.now()});
createObj('attribute', {characterid:char.id, name:'testAttr', current:'myValue'});
profile.push({name:'attrcreate', time:Date.now()});
const attr = findObjs({type: 'attribute', name: 'testAttr', characterid: char.id})[0];
profile.push({name:'attrFound', time:Date.now()});
attr.remove();
profile.push({name:'attrRemoved', time:Date.now()});
char.remove();
profile.push({name:'charRemoved', time:Date.now()});
sendChat('', '/w gm ' + JSON.stringify(profile.map( entry => { return {name:entry.name, time:(entry.time-start)/1000}})));
}
}); The results were: [{"name":"charCreated","time":0.004},
{"name":"charRetrieved","time":0.549},
{"name":"attrcreate","time":0.551},
{"name":"attrFound","time":1.184},
{"name":"attrRemoved","time":1.185},
{"name":"charRemoved","time":1.186}]
As you can see, findObjs is routinely taking > 0.5 seconds, even when it's looking up by what would be a fully indexed composite key in a normal relational database (attribute name + character id). findObjs being slow for big campaigns would be expected and livable-with if it was an edge case for doing arbitrary lookups across random fields - but at the moment it's the only way we can retrieve and work with character attributes, which is pretty fundamental. I can easily end up doing 50+ attribute lookups for a single script command, which is already pushing me dangerously close to 30 seconds without any other work going on. Is there any way that either (a) some more intelligent indexing can be applied to improve this (I know nothing about your backend datastore so I have no idea if this is feasible) or (b) could we have a special function for looking up character attributes that is optimised? Cheers, Lucian