Web 2.0 - when using HTTPS initial page load is 500msec slower

It says

If the external scripts are small, you can inline their contents directly into the HTML document and avoid the network request latency.

and

However, note that inlining also increases the size of the HTML document and that the same script contents may need to be inlined across multiple pages

Since Xojo web app is a SPA (single page app) this warning is not relevant.

In fact, there’s advice for this type of app:

What if I’m using a JavaScript framework to construct the page?
If the content of the page is constructed by client-side JavaScript, then you should investigate inlining the relevant JavaScript modules to avoid extra network roundtrips.

(emphasis mine)

The files range in size from 521 bytes to 300KB with a median size of about 10KB. “Small” of course is relative, but making 25+ requests for ~10KB files is terribly inefficient.

Nobody is suggesting that Xojo Web should replace a full-fledged web server. It is what it is.

However, Xojo Web 2.0 is an app which has bad performance, (for initial page load) and it would be very straightforward to optimize.

The lack of optimization is causing the initial page load to take 3x to 5x as long as it needs to take. In my opinion, fixing this is a no-brainer.

If I were in charge, I would do this:

  • combine the CSS and javascript files into no more than 6 separate files (most web browsers allow only 6 simultaneous connections)
  • see what the problem is with the 304 results taking so long - from my initial investigation, I think the xojo server is doing something wrong with multiple requests (is it serving them up in LIFO order perhaps?) Something doesn’t seem right there.
  • fix the performance bug with SSL sockets. I think there may be an actual bug, or at best, a poor implenetation of cooparative threading as described in <https://xojo.com/issue/66149>
2 Likes

Well, it is relevant. Inline them in HTML and they won’t be cached. You will be sending the same bundle again and again, every time your returning user loads the app.

You’re seeing those 304s stalled because of the protocol, not because Xojo isn’t serving them fast enough. Try to grab those URLs directly with curl, they surely won’t be stalled for seconds.

HTTP/2 can help, as I said. Another cache policy (time-based) can also help, so the browser won’t even have to ask the server if the file has changed or not.

There’s some bug here. Using HTTP/2 instead of HTTP/1.1 is not the cure.

That stack seems a bit weird for sure.
Not behaving like that when using HTTP instead of HTTPS may say something to the investigators.

HTTP/2 can help for sure for the original question, before Mark’s title and content edits.

Enabling HTTPS will change the behaviour. You will start seeing SSL stuff in the stack, not a big surprise.

There are tons of bugs to fix in Xojo Web, but this looks like pursuing ghosts to me.

For clarity, the CustomColumnTypes.js file is generated on-the-fly at runtime because they can be different per session. They also have a high possibility of change and when gzipped they tend to be tiny anyway.

I’m surprised at the 1 second delay, but it should be noted that when a page first loads, most browsers will only make four simultaneous requests to a server to retrieve assets (JavaScript, CSS, images, etc) at a time and the others are queued, so it may just be that.

In terms of the rest of the framework, obviously there are a lot more assets to retrieve in web2 vs web1. That’s what we get for using standardized libraries and publicly licensed controls, but the benefits outweigh in terms of speed.

In web1, we generated and delivered the portion of the framework that was needed for a particular session and each time you made a change, the whole thing need to be pulled to the browser again. We also didn’t always take advantage of gzip so the framework transfer could be quite large. The original system also generated a lot of html snippets on the server and delivered them to the browser over the wire, now html is generated completely client side.

With web2, the framework files won’t change unless we (Xojo) changes something in a major release and even then, only the files that have been changed will be delivered again once per browser, but we check every time because we can’t tell when the page loads if you’ve changed the version of Xojo that you’re using. This is however part of the reason the framework can handle more users per instance… less startup overhead.

In terms of deployment, no, you don’t have to use a load balancer like Apache or Nginx, but if you are deploying your app on the public internet, you certainly should. Not only that you’ll be able to host many more users, they provide you an extra level of protection against bad actors because they can filter out requests that don’t need to go to your app.

2 Likes

See https://forum.xojo.com/t/xojo-web-2-0-faststart/ for a proof-of-concept of inlining the HTML

1 Like

To circle back here - I think the big issue is that the framework files (JS and CSS) are being served with improper cache-control flags.

Here’s an example response header:

Note especiallly this line:

Cache-Control: no-cache, private, max-age=0, must-revalidate, no-transform

These items really are immutable and won’t change (until the Xojo version changes), so no-cache and must-revalidate are really hurting performance here.

A quick fix would be to add the Xojo IDE version number to the filename, e.g.

bootstrap-datepicker-2021r2.1.min.js instead of bootstrap-datepicker.min.js

and then use a proper immutable cache flags with a long lifetime, e.g.

Cache-Control: max-age=365000000, immutable

See Bits Up!: Cache-Control: immutable for a discussion of what the immutable flag does.

Basically, with immutable set, the client does not need to ask the server if the file has changed - this avoids a round-trip network request waiting for the 304 response.

And if the framework version is built into the filename, there won’t be any problems when the user re-builds with a newer version of Xojo.

5 Likes

No need to change anything, just ask for caching and add a GET var like “xojocache” and change that (not used) value every time you need to force a reload, like:

<script src="/framework/bootstrap-datepicker.min.js?xojocache=4321"></script>

Probably a “random number” created at each app loading time, for most of them, is enough. And for those needing changing the contents all the time change them to a not repeating one at runtime, like:

<script src="/session-whatever/custom-whatever.js?xojocache=4321-53773"></script>
3 Likes

Good points - it really depeneds on several factors (public vs. private, proxy vs. naked, etc.) but I think the basic issue is that Xojo Web 2.0 is not delivering optimal cache-control values, and this has non-trivial impacts on performance.

Dont get me wrong: In actual use, I find Xojo Web 2 much faster than 1.0, and it can handle a much higher # of users with ease.

The only issue I’m focusing on here is inital load time, for which Web 2 shows some serious issues, which I feel I’ve diagnosed well and offered good suggestions.

7 Likes

I wasn’t invalidating your points. I was agreeing, adding more information, and enhancing the proposed solutions.

1 Like

The No-cache header doesn’t apply to the browser. It applies to intermediary proxies that may want to cache content and we definitely don’t want them holding onto these files.

Caching behavior is browser-dependent, but I’m pretty sure the combination of max-age=0 and must-revalidate is going to cause most browsers to always check to see if the cache is stale; AND for some resaon, it seems as if Xojo web is no faster delivering a 304 response than a 200 response (and may even be slower at least in some of my tests)

Browsers also cache content if not instructed to avoid it.

Cache-Control: no-cache

This instructs the BROWSER that it must revalidate with the server every time before using a cached version of the URL.

https://web.dev/http-cache/

How is your table created? What controls?

Why not? That is the whole purpose of the cahe isn’t it?

to avoid versioning conflicts, you can add the Xojo version number to the filename as Mike D suggested.

Sorry, didn’t see this response until just now - not sure what this is referring to, can you clarify?

Your initial post shows a table with a number of columns and it looks like a web 1.0 weblistbox.

Just realized, that’s not in your app is it?

To make a table that looks right I’ve had to switch to all containers and its running slowly

That is just a web inspector, must be Safari.

I did this on Web 1.0, works great, Even feels faster than the Native. Not using 2.0 because it still feels like a beta

If I have a table of 20 rows by 20 columns it was taking 3 minutes to load the page in web 1.0. They’ve made some change in 2021r1 that sped it up, but it’s still slow.

Am I going to have to suck it up and make my app look like childish crap in web 2.0?

and any claims of continuing to support web 1.0 are BS.

Today’s comments from clients:

“when I am in, it is either not accepting clicks or moving extremely slow.”

“Literally click the button for the skill…10 secs…then the drop comes down…click the skill…5-10 sec before it shows up, and so on”