JSROOT-based server performance improvement needed

A JSROOT-based “remote server” runs on a “distant machine”.
I get terrible delays when I try to draw something (canvases with histograms) from this “distant machine”.
The “remote server” code which draws and updates them looks (more or less) like this:

function updateP(p){
  var f = "SomeBigFile.root";
  var url = "../jsroot/index.htm?nobrowser&file=../files/" + f + "+&item=" + p + "&monitoring=100000";
  document.getElementById("SomeBigIframe").src = url;
}

I think the problem is that each time one asks for some plot “p”, the entire ROOT file needs to be retrieved (if I remember well, the current JSROOT always unconditionally downloads and “caches” entire ROOT files).
This big ROOT file contains many “plots” (canvases with histograms) inside.
Can I somehow “fix” the performance?
So that it knows the file is already there from the previously drawn “plot” and the newly requested “plot” can be “retrieved” from the “cache” (except when the “monitoring” interval is exceeded, of course).
Note: in the above example code, the name of the ROOT file is “constant”, but in reality, it also depends on the requested “p”. There are several big files, each with many “plots”, but I often only switch between “plots” from the same file (and then I go for another set of “plots” from another file).

Hi,

It is not true. JSROOT reads only file header (~1K), streamer infos, list of items in main directory and finally - data of specified object. Only if HTTP server does not support partial http requests (code 206), full file content can be read as fallback solution.

If the only object from big ROOT file shown with provided method - then your code should be good enough. You can check in browser network console how much data from ROOT file really requested. There you also will probably see if 206 requests working. For me drawing of histogram from hsimple.root produces following requests:

You also can display several objects at once providing items=[item1,item2,item3]&layout=grid2x2 URL parameter. Only data for specified objects will be load.

Or you can use JSROOT API and write small peace of code to open file, get objects and draw them in HTML elements. See read_file.htm demo.

Thanks.

I see no “code 206” anywhere, but maybe I am not looking at the right developer tool window. Where should I check it?

In the “Network” developer tool window, I can clearly see that each time the “monitoring” interval expires or I request a new “plot”, it downloads the full file with a new “timestamp”. And the “Status” for each “GET” there is a “green 200”.

Can it be that the problem is the JSROOT version?
The “remote server” uses an old “JSROOT version ROOT 6.22.04”.

Partial I/O was implemented from very beginning of JSROOT.

ROOT 6.22.04 is really old - examples with modules usage from JSROOT v7.x will not work with it.
But you can check same examples from JSROOT v5 like this one

To see data loading via network - try enable network console and reload page.
Make screenshot or maybe store log in the file - in Firefox there is context menu command “Save all as HAR”.

Which server serves SomeBigFile.root? Is it THttpServer? Or you are using something else?

Thanks again.

I have no possibility of upgrading JSROOT there.
I cannot modify the web server there.

[...]$ curl --head https://far.far.away
HTTP/1.1 200 OK
(...)
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubDomains
(...)
Accept-Ranges: bytes
(...)
X-FRAME-OPTIONS: SAMEORIGIN
Content-Type: text/html

Well, maybe another question. Can it be that the “custom” source code (which then uses JSROOT) can block/disable the “partial I/O” feature? If yes, what should I search for?

Well, I think I found the problem.
In the source code above, in the “url” (right after the ROOT file name), there appears "+&item=". Notice the “+” character. It seems to me it should not be there (or do you think it is intentional?). When I remove this character, the JSROOT starts to behave well (i.e., “partial I/O” works, and I can see “green 206”).

Your server accept ranges - means it should support partial requests.

There is magic symbol “+” after file name which forces JSROOT to load ROOT file as one big BLOB.
Like:

https://root.cern/js/latest/?file=…/files/hsimple.root+&item=hpxpy;1&opt=col

It is exactly how you using it. WHY???

Remove it. Sorry, I did not recognize it immediately - there are many others “+” signs.

I think the “+” character is there because the (binary) ROOT file is updated at regular intervals (every couple of minutes).
Is there a utility that converts a (binary) ROOT file (with many canvases) into a corresponding JSON file (one could then use the “JSON file-based monitoring”)?

Maybe another question.

Can I somehow get the “last modification time” of the “url” ROOT file from inside of the “updateP” function?
I do not mean the local computer’s time “&stamp=” value visible in the “Network” developer tool window.
I mean the file’s actual “last modification time” (retrieved) from the remote server.
The TFile keeps its “creation date and time” and its “last modification date and time”, so retrieving it would be the best idea.
I only want to show it somewhere in the frame, so if JSROOT has some magic option to display it automatically, I don’t need to get these values into my code.

I see. With your update intervals (many seconds) it is very low probability to get errors. And in worse case you just miss one histogram update. Therefore you can skip “+” sign.

One cannot convert complete ROOT file into JSON. But one can convert single object like histogram using TBufferJSON::ExportToFile method.

Correspondent TFile members are decoded by JSROOT - but never displayed.
I just add creation time as tooltip info in file browser like this:

I will try to get this date in the canvas

Great, thanks.
But I guess the “creation time” is not that important.
The “last modification time” is what really matters (i.e., when the plots have been “updated”).
Note that it seems that both these “times” are specific to the “TDirectoryFile” where the drawn canvas/histogram is coming from (not just to the “TFile” itself, but maybe I’m wrong).

I think I would like to get it automatically drawn in a separate “timemstamp” status line (at the bottom of the iframe).
The option “status”, which now exists, can be used as “.../file.root&item=MyC&status”.
Could you please, add a new “timestamp” (or maybe just “time” or “stamp” to be short) option that would add another status line?
In this (optional) status line, the “file name”, the drawn “object name”, and its directory’s “last modification time” could be shown. That would be perfect for me.

I change to modified time.

Since several version jsroot has optdate and optfile URL options. It is equivalent of gStyle.SetOptDate() and gStyle.SetOptFile() methods. I add now optdate=2 and optdate=3 options.
First shows file creation time, second - file modification time.

Can be used as:

https://jsroot.gsi.de/dev/?file=…/files/hsimple.root&item=hpx;1&optdate=2&optfile

https://jsroot.gsi.de/dev/?file=…/files/hsimple.root&item=hpx;1&optdate=3&optfile

Looks great.

I assume the shown “times” are in the timezone used when the ROOT file was created/modified (or can I get them in UTC even if I do not know this “external” timezone?).

A small question … can I somehow add these two options (“&optdate=3&optfile”) to some “default” settings using something like:
document.getElementById("simpleGUI").setAttribute(...);

JSROOT displays time with browser default timezone.

I add utc URL parameter to switch display into UTC timezone.

I also extend meaning optfile parameter.

optfile=1 is file name as in “normal” ROOT
optfile=2 is full URL to the file
optfile=3 is item name of main drawn object in the canvas

Now to display full file URL and modification time in UTC one should do:

https://jsroot.gsi.de/dev/?file=…/files/hsimple.root&item=hpx;1&optdate=3&optfile=2&utc

You can modify global settings in the canvas -> Settings -> gStyle -> Canvas context menu. Like:

After you adjust settings, you can invoke canvas -> Settings -> Save settings menu command.
This store JSROOT settings as cookies and will be reused every time JSROOT started new.

Fantastic.

The “TDirectoryFile” contains the “creation time” and the “last modification time” as the “TDatime”, which is always some “local time of the machine where the object was created”.
Do you think the conversion into UTC, on a completely different machine elsewhere in the world, is “reliable” (considering the local timezone)?
(I think I can test it next week when new ROOT files are ready, as they will always be several tens of minutes “old” at most, and from a different timezone.)

Well, it seems I like: “&optdate=3&utc&optfile=3
Now, I would like to “hardcode” it into some scripts.
In the " updateP" function, I can easily add it to the “url” string (no problem here).
But, I also use a custom version of your “simpleGUI” and I would like to add some magic line that will set these options (without the user’s intervention):

document.getElementById("simpleGUI").setAttribute("path", "/My/Files/");
document.getElementById("simpleGUI").setAttribute("files", "f1.root;f2.root;f3.root");
... here I would like to "inject" the default options ... optdate=3 utc optfile=3 ...
import { buildGUI } from 'https://jsroot.gsi.de/dev/modules/gui.mjs';
... or maybe here ...
buildGUI("simpleGUI");
... or maybe here ...

Note: it should not be stored “permanently” for the user (it should be valid only for the “current GUI session”).

BTW. I noticed two small problems. The displayed “optdate” covers the “tool buttons” below. The displayed “optfile” does not change its position when the browser’s window is resized (e.g. “maximized”).

If you write your own JavaScript, then just do:

import { gStyle, settings } from 'https://jsroot.gsi.de/dev/modules/core.mjs';

gStyle.fOptFile = 3;
gStyle.fOptDate = 3;
gStyle.fDateY = 0.05;
gStyle.fDateX = 0.05;
settings.ToolBarVert = true; // optional, to layout buttons vertically

And the “utc” setting?

(I’ll play with it tomorrow.)

settings.TimeZone = 'UTC';

Some docu about settings is: settings - Documentation

But it is not always complete :frowning:

Many, many thanks.

A small warning for the “optdate” display.
The retrieved value is always in the “local time of the machine where the object was created”, and it does not know its timezone (so, using the “utc” option is not correct unless one’s timezone is precisely the same).

For example… my local timezone now is “+1 hour” to UTC and “-8 hours” to the ROOT file creator’s timezone.
A file was created on “Feb 24 03:49 UTC” and JSROOT shows “24/02/2024, 12:49:03”.
Another file was created on “Feb 26 19:25 UTC” and JSROOT shows “27/02/2024, 04:25:02”.
(Using the “utc” option modifies the time shown in JSROOT by “-1 hour”, as expected for my local timezone.)

Another small problem … I set the “gStyle.fOptFile = 3; gStyle.fOptDate = 3; settings.ToolBarVert = true;”, and all are correctly shown in the browser tab.
When I execute (for some canvas/histogram) “Draw in new tab”, these settings are not propagated to the newly created tab.
Can I somehow get them automatically set there, too?
The generated URL in the new tab always ends with “&opt=” (what is it for?), so maybe it could also automatically get “&optdate=3&utc&optfile=3&opt=” (well, the “ToolBarVert” would be unfortunately lost).
Maybe a good idea would be to ensure all user’s “gStyle” settings are always copied to the new tab (you mentioned a cookie valid for the current session?).

Automatic way would be saving all settings in the cookies.
Then also default JSROOT HTML page will use them - no need to create long URL
with all possible parameters.

To do this:

import { saveSettings, saveStyle } from 'https://jsroot.gsi.de/dev/modules/gui/utils.mjs';

saveSettings();
saveStyle();

And minimal docu: Global - Documentation

Many thanks.

I guess I am missing something here.
I added your magic lines, and I get no warnings/errors on the “Console”, but “Draw in new tab” still does not see my modifications (I mean, I click the canvas/histogram name, in the browser’s tab, with the right mouse button and select “Draw in new tab”).

BTW. What is this “&opt=” for? It seems to be always there and always empty.