SoFunction
Updated on 2025-03-01

Detailed explanation of the execution time of the asynchronous function record

calc

calc It is an asynchronous function that we want to do analysis (performance analysis). By convention, its last parameter iscallback. We use it like thiscalc

calc(arg, (err, res) => (err || res))

Perhaps, the easiest rightcalc The way to analyze performance with such a function is to add a timing logic to where we need to analyze:

const t0 = ()
calc(arg, (err, res) => {
 const t1 = () 
 (`Log: time: ${t1 = t0}`)
 (err || res)
})

However, this is not a reusable solution. Every time we want to time a function, we have to introduce a t0 in the outer scope and change itcallback to measure and record time.

The ideal way for me is to be able to time it just by wrapping an asynchronous function:

timeIt(calc)(arg, (err, res) => (err || res))

timeIt It is necessary to be able to perform analysis and record execution time for each asynchronous function well.

NotetimeIt(calc) Having the same function signature as the original calc function, i.e. they accept the same parameters and return the same value, it just adds a feature to the cale (a feature that can be recorded time).

calc and timeIt(calc) can be replaced by each other at any time.

timeIt It is itself a higher-order function because it accepts a function and returns a function. In our example, it accepts the calc asynchronous function and returns a function with the same parameters and return value as calc.

The following shows how we implement the timeIt function:

const timeIt = ((report, f) => (...args) => {

 const t0 = ()
 const nArgs = (args)
 const callback = (args)

 ((...args) => {
 const t1 = ()
 callback(...args)
 report(t1 - t0, ...args)
 })

 f(...nArgs)

})

const timeIt1 = timeIt(
 (t, err, res) => (`Log: ${err || res} produced after: ${t}`)
)

const calc = (x, y, z, callback) =>
 setTimeout(() => callback(null, x * y / z), 1000)


calc(18, 7, 3, (err, res) => (err || res))

timeIt1(calc)(18, 7, 3, (err, res) => (err || res))

thistimeIt Implementation accepts two parameters:

report: A function is used to generate analysis results

f: Asynchronous function we want to perform analysis

timeIt1 It is a convenient and practical function, it just uses Record time measurement results. We give more generaltimeIt Functions passed inreport Parameters to define it.

We achieved the goal, and now we can just wrap the asynchronous function intimeIt1 It can be timed:

timeIt1(calc)(18, 7, 3, (err, res) => (err || res))

GeneraltimeIt The function receives areport The callback function and an asynchronous function and returns a new asynchronous function. This asynchronous function has the same parameters and return value as the original function. We can use this:

timeIt(
 (time, ...result) => // report callback: log the time
 , asyncFunc
)(
 parameters…, 
 (...result) => // result of the async function
)

Now let's go deepertimeIt Implementation of . We can simply generate a general function liketimeIt1,becausetimeIt use Corey has become.

I don't plan to discuss coriculization in this post, but the following code demonstrates the main usage of coriculization:

const f = ((x, y) => x + y)
f(1, 10) // == 11
f(1)(10) // == 11

const plus1 = f(1)
plus1(10) // == 11

On the other hand, there are several problems with timeIt implemented in this way:

(...args) => {
 const t1 = ()
 callback(...args)
 report(t1 — t0, ...args)
}

This is an anonymous function (also known as lambda, callback) which is called after the original function is executed asynchronously. The main problem is that this function has no mechanism to handle exceptions. ifcallback throw an exception,report It will never be called.

We can add onetry / catchTo thislambda In the function, however, the root of the problem iscallback andreport Yes twovoid functions, they are not associated.timeIt Contains two continuations (report andcallback). If we were justconsole Record the execution time or if we determine itreport stillcallback No exception is thrown, then everything is normal. But if we want to perform some behavior based on the analysis results (so-called automatic scaling) then we need to strengthen and clarify the continuation sequence in our program.

Okay, I hope the full content of this article will be helpful to everyone's study and work. If you have any questions, you can leave a message to communicate.