Jiboux said: The html should have very little effect on sheet load performance. I would check how much you are doing in your sheetworkers in response to the sheet open event. If you have multiple listeners to that event and each one is getting and setting attributes, that will be roughly 100ms of delay per listener. We actually conducted some measurement to conclude we had to do something with the HTML... On my side, even a very big sheet loads in a semi-reasonable time (10-15s) but my partner was able to build a configuration with a baseline of 90s approx. Removing altogether the code for the Sheetworker had a "marginal" effect (90s=>80s) while removing big chunks of the HTML especially complete repeating_sections had much more effect. Also I was able (maybe it can be help identifying the cause), to identify 2 phases in the HTML loading: Phase 1 : the pop-up window is displayed, with the roll20 native Sheet/Bio etc tabs, but nothing is displayed Phase 2 : The custom sheet has appeared but is not responsive with the D20 loading icon. The Phase using most of the loading time is phase 1. I doubt that this is the html itself. If your sheetworkers did not cause a large decrease in the load time, then I would look at your CSS. If you are doing a lot of descendent selectors and generic targeting, this can slow the CSS render engine down (particularly in repeating sections which wind up needing to run the same CSS render multiple times). If I recall, you are building an official sheet with a compendium. This means there is no reason to have all that embedded json data. Offload that to the compendium instead of having it hard coded into the sheet. We will run some more measurements, but this was done with the intent to not put the users behind a paywall. In particular we are "servicing" a big community that is on a Westmarch game with above 100 players... Despite many users having the compendium, the limit to 15 for compendium sharing makes that many "entry users" don't have access... Of course if in measurement we find it has a good effect, I'll try to cut in the database, but I would like to keep a minimum to service those users. Having things in the compendium does not mean that they have to be behind a paywall. Expansion 0 is always available to everyone that uses the compendium regardless of if they have purchased content or not (e.g. the 5e OGL SRD). Additionally, you can designate certain compendium expansions as free to use (e.g. the 5e 2014 playtest rules). And then, on the subject of the overall sheet size. I don't have anything specific, but I build extremely complex sheets with probably some of the most (if not the most) complex features on Roll20. I have built sheets that run into the 10s of thousands lines of code, however I have found that as I have gotten more experience, a sheet that is 20k lines of html/js is usually a sign that there is a lot of extraneous code. As an example, see the official star finder sheet (20k html+js), which was the first sheet I ever wrote, vs genefunk2090 (6.5k html+js), a sheet i wrote a couple years ago. Both of these sheets have a very similar feature set, but genefunk is less than a third of the starfinder sheet. The reason is genefunk is newer and I had learned how to refactor my code to be more efficient. You can compare both to the walking dead, which is probably the most advanced sheet in the repo but it is almost the same size as genefunk even though it does things that were impossible when the genefunk sheet was written. Would you mind developping a bit on the type of optimizations you did ? We don't have for restarting the sheet in a different style (I have been several times told about technological debt, but I just don't have a second pandemic ahead of me to start from scratch :D). One of the directions I have been wanting to go in the past is "multiplexing", i.e. we have a lot of different cases and exceptions that are coded each on a single boolean attribute... I'd like to reduce the total attributes by putting them on an HEX instead, and both the API and Sheetworker will work well with that, but we often display on the sheet this with a clickable icon ( a checkbox with a CSS for the icon)... I don't see an easy CSS/HTML to implement that easy clickable icon ( testing only a bit of an hex, changing only a bit from an hex). There isn't really a way to efficiently multiplex a checkbox. You can have a checkbox that can have multiple values, but you still have to have multiple versions of that checkbox (one for each value, and then all checkboxes have 0 as their unchecked): <input type="checkbox" name="attr_multi_check" value="1">
<input type="checkbox" name="attr_multi_check" value="2">
<input type="checkbox" name="attr_multi_check" value="3">
Of course, checkboxes in Roll20 can still only have a single value assigned to the attribute at a time. If you are wanting to do something like store the values of multiple "attributes" in a single attribute, it isn't something that I would expect to provide any actual benefit. The reason is that you will still need multiple html elements to provide interaction points for each possible value, and the data still has to be saved to the firebase database. Storing the data as individual attributes like: attribute_1: 2
attribute_2: 'some string'
attribute_3: '@{my_call}' vs. storing them as JSON in a single attribute: json_attribute: {"attribute_1":2,"attribute_3": "some string", "attribute_3":"@{my_call}"} There's no real performance difference between those two from a network and database standpoint. If anything, the stored JSON would be infinitesimally slower (unnoticeably so unless you were doing this with a MASSIVE dataset) on the client side as you'd have to actually create the JSON for storage and parse the JSON after you had gotten the attribute values to use it. I know you mentioned doing this with data encoded in HEX, but the point holds. There's just very little difference in a project the size of a character sheet between encoded data in a single attribute and that same data unencoded in multiple attributes. I've done multiple speed tests of the sheetworker system and any difference in processing time based on data size is massively outweight by network latency. Regardless of if you are working with a single attribute or 100,000 attributes, the getAttrs and setAttrs calls are going to take the same amount of time (10's of ms and 100's of ms respectively). As for the optimizations that I did, I'm not sure I can quantify them exactly, but they fall into a few broad categories: More efficient CSS. Along with better understanding of CSS, modern CSS has gained many features that were impossible or used to required a lot of convoluted CSS to accomplish. Switching to these once they are available on R20's supported browser allows your CSS to be quicker, smaller, and easier to understand. The above also allows more efficient HTML. I found ways to create the same common constructs that I needed without needing extreme levels of nesting. CSS grid, flexbox, and multi columns are essential for this as they allow extremely flat html constructs to create extremely complex layouts with a minimum of html and CSS code. More efficient Sheetworkers. Inefficient sheetworkers can cause extreme lag on a sheet. Since my first sheet, Starfinder, I've developed and switched to the K-scaffold sheet framework which takes care of my event handling and event cascades for me. This allows my sheetworkers to be extremely compact with lots of reusable code. Something that I never did, but many sheets do make use of is Roll20 autocalculated attributes using the disabled="true" flag on an input to tell Roll20 to calculate the display value from a formula found in the value. These are extremely inefficient and having as few as a hundred of them in a sheet can cause noticeable load lag on a sheet. Note that having them in repeating sections is especially bad because as users add repeating items, you are adding more instances of the auto calc that have to be handled by Roll20. If you are using ANY autocalculated attributes, switch them to sheetworker calculated instead. NOTE: Your descriptions of your sheet's load times matches almost exactly what happens when this is the issue. Using an html/scss template language can help with this because it is easier to see where you are writing more than you need than it is with raw html. And using a pre built sheets infrastructure can also help. However, both can also mask inefficient code, so they have to be used carefully. We are using extensively CSS, but one of the things I am concerned is the quantity of stuff that is loaded but not displayed at a single moment... The sheet has an overview tab, where an overview of each of the repeating sections is shown, and then mostly a tab for each of the repeating_section, where you can actually set the details of each item... For each of the repitems there can be a lot of detailed parameters, so at a given moment there is certainly 80% of the HTML that is loaded but in display:none... This is where I am thinking there may be something. As said, at this point there is not the dedication to actually start from a clean slate. I'd take a hard look at your CSS and see if it is overly complex. In my experience this is far more likely to cause load lag than the HTML itself. Of course HTML and CSS complexity go hand in hand. If your HTML is extremely complex and nested, then your CSS will need to be as well. And the final piece is unintuitive. A great deal of what used to require the API to do can now be done within the sheet. I would recommend moving anything that can possibly be done sheet side from the API to the sheet. In my experience, in order for right sheet-API integration, you wind up needing many extra attributes to allow the sheet and the API script to communicate with each other effectively. Moving that functionality sheet side 1) simplifies your code base, 2) will likely reduce the attributes you require, 3) will probably be faster since you will probably need fewer network calls, and 4) will give all users access to those features. This is something that we have been regularly doing feature by feature... Stuff that we will always keep in the API: - Actual rolling ( we have implemented sequences like attacking / rolling damage / applying damage with single or multiple targets with built-in many of the rules and comparisons that trigger new stuff happening... I don't believe sheetworker can really handle something that involves more than one character) -Complex user interfaces (Queries are not as easy for users with than sending to the chat various buttons to click and choose from) But we keep looking for functions that could be done in the sheet... Thanks a lot for your support and advice I would do the actual rolling on the sheet. There are many ways to have sheets affect and react to events on other sheets. You can take a look at the Walking Dead sheet for an example of this in the extreme. The Walking Dead sheet allows NPCs, locations, and factions to be embedded in one another with live updating of their stats across all instances of the given entity regardless of where the change was entered. Similarly, complex user interfaces can be done via the sheet as well. You can output the same chat buttons that you are sending via the API, but have them call back to buttons on the sheet instead of listeners in the API. Additionally, you can pass extra data in those buttons . In many ways, the sheet can react more robustly to a chat button click than the API can. The only thing that the API is required for is if you are doing 1) complex interactions with the turn tracker (e.g. adding multiple instances of an entity or custom sorting the turn tracker), 2) anything with dynamic lighting/vision, 3) manipulating tokens or other elements on the map, or 4) doing anything with the journal or page list.