When it comes to delaying statistics, one of the nouns that must be thought of is "performance testing," Yes, in Redis's Redis_benchmark file, it does use the information in the deferred file. The official interpretation of this document in Redis:
/* The latency monitor allows to easily observe the sources of latency
* In a Redis the using the instance command . Different Latency
* sources are monitored, like disk I/O, execution of commands, fork
* system call, and so forth.
*
* Latency listener can listen to many simple resources in Redis, such as I/O disk operation, execute some instructions,
* Fork to create the child thread operation and so on listening.
* ----------------------------------------------------------------------------
In Redis, the whole process is simple, and he maintains a list of statistics for each event, each containing a collection of samples, each containing the creation time of the sample and the delay time of the sample. event== "Sampleserieslist is a dictionary mapping relationship. Here's a look at the key collection point, called the Latencysample acquisition point structure definition:
/* Representation of a latency sample:the sampling time and the latency * observed in milliseconds.////
Delay sample * *
struct Latencysample {
//Delay Sample creation time
int32_t/* We don ' t use time_t to force 4 bytes Usage everywhe Re. * *
//delay time, in milliseconds
uint32_t latency/* latency in milliseconds. */
};
The dictionary does not maintain a sample node, but rather a node list structure:
/* The Latency Time series for a given event.
Next, sample to store. //
Maximum delay uint32_t max//MAX
Latency observed for this event. *//
Recent delay record
struct Latencysample SA Mples[latency_ts_len]; /* Latest history. */
};
In the design of Redis code, because the delay is used to test and analyze the result, the author also designed the data statistic structure used in the later analysis report.
/* Latency statistics structure.
observed since latest reset. *
//////Average sample delay time
uint32_t avg; /* Average of current samples. * *
//sample Minimum delay time
uint32_t min; /* Min of current samples. * *
//sample Maximum delay time
uint32_t Max; /* Max of current samples. /* Mean Absolute deviation. * *
The total number of//samples
uint32_t samples; /* Number of non-zero samples. /* Number of seconds since and now. */
};
The meaning is very direct, then a simple sample how to carry out the detection of the event.
/* Start monitoring an event. We just set the current time.
/* To set up a listener for an event, set the current time *
/#define LATENCYSTARTMONITOR (Var) if (server.latency_monitor_threshold) {\
var = mstime (); \
} else {\
var = 0; \
}/* End Monitoring ' An
event, compute the ' difference ' with the ' current ' to
check The amount of time elapsed. /
//* End of the monitoring, calculate how much time
/#define Latencyendmonitor (Var) if (server.latency_monitor_threshold) {\
var = Mstime ()-Var; \
}
Very simple, record start time, record end time, the middle difference is the delay time, if beyond the given time range, added to the delay list:
/* ADD The sample only if the elapsed time is >= to the configured threshold. * *
If the delay time exceeds server.latency_monitor_threshold, then add sample to the delay list
/* * #define LATENCYADDSAMPLEIFNEEDED (event, var) \
if (server.latency_monitor_threshold &&
(Var) >= server.latency_monitor_threshold) \
Latencyaddsample ((event), (Var));
We focus on, latencyaddsample, is to add the sampling node to the record, the steps are as follows:
1. According to the incoming event event, in Server.latency_events find the Val with key event events, that is, a latencytimeseries
2. Add a new sample in this latencytimeseries struct latencysample Samples[latency_ts_len]
The implementation code is as follows:
/* ADD The specified sample to the specified time series "event". * This function is usually called via latencyaddsampleifneeded (), which is a macro that only adds the sample if the late Ncy is higher than * server.latency_monitor_threshold.
* * * Add sample to the specified Event object's sample list/void Latencyaddsample (char *event, mstime_t latency) {//Find the event corresponding to the delay sample record structure
struct Latencytimeseries *ts = Dictfetchvalue (server.latency_events,event);
time_t now = time (NULL);
int prev; /* Create The time series if it is does not exist.
*/if (ts = = NULL) {ts = zmalloc (sizeof (*ts));
Ts->idx = 0;
Ts->max = 0;
memset (ts->samples,0,sizeof (ts->samples));
If TS is empty, re-add, an event, corresponding to a latencytimeseries Dictadd (Server.latency_events,zstrdup (event), TS); }/* If the previous sample is in the same second, we update our old sample * If This latency was > of the old One, or just return. * * prev = (Ts->idx + Latency_ts_len-1)% Latency_ts_len; if (Ts->samples[prev].time = Now) {if (Latency > Ts->samples[prev].latency) ts->samples[
Prev].latency = latency;
Return
///For sample Assignment Ts->samples[ts->idx].time = time (NULL);
Ts->samples[ts->idx].latency = latency;
if (Latency > Ts->max) Ts->max = latency;
ts->idx++;
if (Ts->idx = = latency_ts_len) ts->idx = 0;
}
After the node is out, of course, the structure of the analysis of statistics, then used the latencystats structure;
/* Analyze The Samples avaialble for a given event and return a structure * Populate with different metrics, average, MAD
, Min, Max, and so forth.
* Check latency.h definition of struct latenctstat for more info. * If The specified event has no elements the structure is populate with * zero values. * * * Analysis of a time event delay results, the results of the information stored in the LATENCYSTATS structure of the * * * analyzelatencyforevent (char *event, struct latencystats *ls) {s
Truct latencytimeseries *ts = Dictfetchvalue (server.latency_events,event);
Int J;
uint64_t sum; Initialization delay statistic result structure variable Ls->all_time_high = ts?
ts->max:0;
Ls->avg = 0;
ls->min = 0;
Ls->max = 0;
Ls->mad = 0;
ls->samples = 0;
Ls->period = 0;
if (!ts) return; /* The populate everything but the MAD.
* sum = 0;
for (j = 0; J < Latency_ts_len; J +) {if (Ts->samples[j].time = 0) continue;
ls->samples++; if (ls->samples = = 1) {ls->min = LS->max = ts->samples[j].latency; else {//Find the delay maximum and minimum delay time if (Ls->min > ts->samples[j].latency) ls->min =
ts->samples[j].latency;
if (Ls->max < ts->samples[j].latency) Ls->max = ts->samples[j].latency;
Sum + + ts->samples[j].latency; /* Track The oldest event time in Ls->period.
T;period = ts->samples[j].time; }/* So far avg is actually the sum of the latencies, and period are * the oldest event time. We need to make the second a range of seconds.
*/if (ls->samples) {ls->avg = sum/ls->samples;
Ls->period = Time (NULL)-ls->period;
if (Ls->period = = 0) Ls->period = 1; }/* Second pass, COMPUTE MAD. *////calculation average relative error, and flatAverage delay compared to sum = 0;
for (j = 0; J < Latency_ts_len; J + +) {int64_t delta;
if (Ts->samples[j].time = = 0) continue;
Delta = (int64_t) ls->avg-ts->samples[j].latency;
if (Delta < 0) Delta =-delta;
sum = Delta;
} if (ls->samples) Ls->mad = sum/ls->samples;
}
Of course, you can also use these collected points, draw a micro-line map, more image display:
#define LATENCY_GRAPH_COLS 80/* Using the delay of the sample point, draw the corresponding micro-line map * * SDS latencycommandgensparkeline (char *event, struct
Latencytimeseries *ts) {int J;
struct sequence *seq = Createsparklinesequence ();
SDS graph = Sdsempty ();
uint32_t min = 0, max = 0;
for (j = 0; J < Latency_ts_len; J +) {int i = (ts->idx + j)% Latency_ts_len;
int elapsed;
Char *label;
Char buf[64];
if (Ts->samples[i].time = = 0) continue; /* Update min and Max.
*/if (seq->length = 0) {min = max = ts->samples[i].latency;
else {if (Ts->samples[i].latency > Max) max = ts->samples[i].latency;
if (ts->samples[i].latency < min) min = ts->samples[i].latency; }/* Use as label the number of Seconds/minutes/hours/days * ago the event happened.
*/elapsed = time (NULL)-ts->samples[i].time; if (Elapsed <) SnpriNTF (Buf,sizeof (BUF), "%ds", elapsed);
else if (elapsed < 3600) snprintf (buf,sizeof (BUF), "%DM", ELAPSED/60);
else if (elapsed < 3600*24) snprintf (buf,sizeof (BUF), "%dh", elapsed/3600);
else snprintf (buf,sizeof (BUF), "%dd", elapsed/(3600*24));
Label = Zstrdup (BUF);
Sparklinesequenceaddsample (Seq,ts->samples[i].latency,label); Graph = sdscatprintf (graph, "%s-high%lu ms, low%lu ms) \ n", event, (%lu
Ed long) Max, (unsigned long) min, (unsigned long) ts->max);
for (j = 0; J < Latency_graph_cols; j +) Graph = Sdscatlen (graph, "-", 1);
Graph = Sdscatlen (graph, "\ n", 1);
Call the Sparkline function to draw the micro-line Graph graph = sparklinerender (Graph,seq,latency_graph_cols,4,sparkline_fill);
Freesparklinesequence (seq);
Returns a micro-line graph string return graph;
}
The Redis also encapsulates commands for external invocation, which is not parsed, that is, a composite call to the above method:
/*----------------------------Latency API---------------------------------*
/void Latencymonitorinit (void)/* Latency listener initialization, creating an event Dictionary object
/void Latencyaddsample (char *event, mstime_t latency)/* Add sample to the named Event object's sample list */< C2/>int latencyresetevent (char *event_to_reset)/* Resets the delay of event events, deletes the record of event in the dictionary
/void Analyzelatencyforevent ( Char *event, struct latencystats *ls)/* Analyzes the delay result of an event, and the result information is deposited in the LATENCYSTATS structure
/SDS createlatencyreport (void)/ * According to the results of the delay sample, create a better reading analysis report * * * *
latencycommandreplywithsamples (redisclient *c, struct latencytimeseries *ts )
void latencycommandreplywithlatestevents (redisclient *c)
SDS latencycommandgensparkeline (Char *event, struct latencytimeseries *ts)
void Latencycommand (Redisclient *c)
The analysis of Redis delay class files is also over, analysis of such a long time Redis Redis code, feel that every piece of code will have his bright spot exists, analysis of 30 no down, or learned a lot of online learning not to learn, online more is the Redis mainstream thinking of learning, Like some small points, and only their own taste, they can truly experience.