qt4cg / qtspecs

QT4 specifications
https://qt4cg.org/
Other
27 stars 15 forks source link

non-deterministic time #76

Open benibela opened 3 years ago

benibela commented 3 years ago

The current-date/Time functions are deterministic, so they always return the same time, which is very confusing to everyone

There could be actual-current-date/Time functions that return the actual time non-deterministically. Or call it wall-date/Time or system-date/Time

michaelhkay commented 1 year ago

I agree this would be useful, although there is a danger of misuse. Saxon offers this capability as saxon:timestamp(). Perhaps the name fn:dateTimeStamp(), to align with the XSD 1.1 type name, would be appropriate.

joewiz commented 1 year ago

eXist also uses util:system-dateTime(): https://exist-db.org/exist/apps/fundocs/index.html?q=util:system-dateTime.

ndw commented 1 year ago

I have only used saxon:timestamp() rarely, but I have been very greatful for it when I have.

I could live easily with either fn:dateTimeStamp() or fn:system-dateTime().

michaelhkay commented 1 year ago

I had a go at speccing this up, which was going fine until I started writing the notes giving advice on how to use it for performance instrumentation, avoiding the hazards of variable inlining and lazy evaluation in a construct like

let $start := system-dateTime();
let $doc := doc('abc.xml')
let $totalTime = system-dateTime() - $start;

and I found it very difficult to give advice on how to do this in a way that had a good chance of working with all implementations.

So it occurred to me that a better solution might be a function

fn:monitor(doc('abc.xml')) as record(value, startTime, endTime)

which returns a map containing fields value - the value of the first argument, plus the start time and end time, or perhaps just their difference.

There's still a bit of an assumption that the implementation is capable of getting the start time before the first argument is evaluated, which implies some kind of lazy evaluation, but that's putting the onus on the implementor, not on the user, and I would think there's a reasonable prospect of getting it interoperable.

Would we want this as well as system-dateTime(), or in place of it?

Would we want to return start and end time, or just duration? If duration, then as an xs:duration or as a number?

Note that there's still a degree of non-determinism, in that two calls on fn:monitor() with the same argument value are expected to return different results. And there's still a danger of optimization invalidating any measurements, e.g. if

avg(1 to 1000 ! (monitor(my:f('foo'))?duration) )

does any unexpected loop-lifting. But those difficulties seem more manageable than the problems with order of evaluation of independent local variables.

ChristianGruen commented 1 year ago

Exactly my thoughts. We advise our users against using non-deterministic functions for doing performance measurements. Instead, we provide prof:time, which output the runtime similar to fn:trace, and prof:track, which returns the runtime of an expression along with the result. In practice, because of suppressed optimizations, the returned time may deviate a lot from the runtime without monitoring, so the results need to be interpreted accordingly.

I also encountered cases which don’t revolve about performance. For example, if you write logs during a time-consuming process, it can be important to have the exact timestamp when a particular subprocess was finished.

@benibela Which use cases did you have in mind when proposing the function?

ndw commented 1 year ago

I don't recall wanting a timestamp specifically for performance testing, so I don't think fn:monitor is a really good replacement for system-dateTime. If, in the interest of minimizing the number of functions in the library, we decide that it should be a replacement, it's going to be important that it return the start time since that might be the only bit I care about!

Would a design something like random-number-generator have any value? I'm thinking of a function that returns a start time, a duration (initially 0), and a function that when called will return a new start time, the duration since the last call, and another function to repeat the process.

michaelhkay commented 1 year ago

I think there's still a use-case for system-dateTime in constructing the output of fn:trace() or xsl:message; but perhaps that can be achieved with mechanisms specific to that function/instruction.

benibela commented 1 year ago

Things users wanted to do:

ndw commented 1 month ago

At the f2f, we discussed some of the details and seemed to be favoring the idea that it would be easiest to make the eager evaluation a quality of implementation issue.