mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-25 15:11:10 +00:00
[MAJOR] changed TV_ETERNITY to ~0 instead of 0
The fact that TV_ETERNITY was 0 was very awkward because it required that comparison functions handled the special case. Now it is ~0 and all comparisons are performed on unsigned values, so that it is naturally greater than any other value. A performance gain of about 2-5% has been noticed.
This commit is contained in:
parent
96bcfd75aa
commit
a6a6a93e56
@ -26,7 +26,18 @@
|
||||
#include <sys/time.h>
|
||||
#include <common/config.h>
|
||||
|
||||
#define TIME_ETERNITY -1
|
||||
/* eternity when exprimed in timeval */
|
||||
#ifndef TV_ETERNITY
|
||||
#define TV_ETERNITY (~0UL)
|
||||
#endif
|
||||
|
||||
/* eternity when exprimed in ms */
|
||||
#ifndef TV_ETERNITY_MS
|
||||
#define TV_ETERNITY_MS (-1)
|
||||
#endif
|
||||
|
||||
#define TIME_ETERNITY (TV_ETERNITY_MS)
|
||||
|
||||
|
||||
/* returns the lowest delay amongst <old> and <new>, and respects TIME_ETERNITY */
|
||||
#define MINTIME(old, new) (((new)<0)?(old):(((old)<0||(new)<(old))?(new):(old)))
|
||||
@ -72,7 +83,6 @@ REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2);
|
||||
*/
|
||||
REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval *tv2);
|
||||
|
||||
|
||||
/* sets <tv> to the current time */
|
||||
REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
|
||||
{
|
||||
@ -87,13 +97,13 @@ REGPRM1 static inline struct timeval *tv_now(struct timeval *tv)
|
||||
*/
|
||||
REGPRM2 static inline int tv_cmp(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
if (tv1->tv_sec < tv2->tv_sec)
|
||||
if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
|
||||
return -1;
|
||||
else if (tv1->tv_sec > tv2->tv_sec)
|
||||
else if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
|
||||
return 1;
|
||||
else if (tv1->tv_usec < tv2->tv_usec)
|
||||
else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
|
||||
return -1;
|
||||
else if (tv1->tv_usec > tv2->tv_usec)
|
||||
else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@ -104,11 +114,11 @@ REGPRM2 static inline int tv_cmp(const struct timeval *tv1, const struct timeval
|
||||
*/
|
||||
REGPRM2 static inline int tv_cmp_ge(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
if (tv1->tv_sec > tv2->tv_sec)
|
||||
if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
|
||||
return 1;
|
||||
if (tv1->tv_sec < tv2->tv_sec)
|
||||
if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
|
||||
return 0;
|
||||
if (tv1->tv_usec >= tv2->tv_usec)
|
||||
if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@ -122,7 +132,7 @@ REGPRM2 static inline unsigned long tv_diff(const struct timeval *tv1, const str
|
||||
unsigned long ret;
|
||||
|
||||
ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
|
||||
if (tv2->tv_usec > tv1->tv_usec)
|
||||
if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
|
||||
ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
|
||||
else
|
||||
ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
@ -142,7 +152,7 @@ REGPRM2 static inline unsigned long tv_remain(const struct timeval *tv1, const s
|
||||
return 0; /* event elapsed */
|
||||
|
||||
ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
|
||||
if (tv2->tv_usec > tv1->tv_usec)
|
||||
if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
|
||||
ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
|
||||
else
|
||||
ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
@ -151,42 +161,75 @@ REGPRM2 static inline unsigned long tv_remain(const struct timeval *tv1, const s
|
||||
|
||||
|
||||
/*
|
||||
* zeroes a struct timeval
|
||||
* sets a struct timeval to its highest value so that it can never happen
|
||||
* note that only tv_usec is necessary to detect it since a tv_usec > 999999
|
||||
* is normally not possible.
|
||||
*
|
||||
*/
|
||||
|
||||
REGPRM1 static inline struct timeval *tv_eternity(struct timeval *tv)
|
||||
{
|
||||
tv->tv_sec = tv->tv_usec = TV_ETERNITY;
|
||||
return tv;
|
||||
}
|
||||
|
||||
/*
|
||||
* sets a struct timeval to 0
|
||||
*
|
||||
*/
|
||||
REGPRM1 static inline struct timeval *tv_zero(struct timeval *tv) {
|
||||
tv->tv_sec = tv->tv_usec = 0;
|
||||
return tv;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns 1 if tv is null, else 0
|
||||
* returns non null if tv is [eternity], otherwise 0.
|
||||
*/
|
||||
REGPRM1 static inline int tv_iseternity(const struct timeval *tv)
|
||||
{
|
||||
if ((tv->tv_sec | tv->tv_usec) == 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#define tv_iseternity(tv) ((tv)->tv_usec == TV_ETERNITY)
|
||||
|
||||
/*
|
||||
* returns the first event between tv1 and tv2 into tvmin.
|
||||
* a zero tv is ignored. tvmin is returned.
|
||||
* returns non null if tv is [0], otherwise 0.
|
||||
*/
|
||||
REGPRM3 static inline const struct timeval *tv_min(struct timeval *tvmin,
|
||||
const struct timeval *tv1,
|
||||
const struct timeval *tv2)
|
||||
{
|
||||
#define tv_iszero(tv) (((tv)->tv_sec | (tv)->tv_usec) == 0)
|
||||
|
||||
if (tv_cmp2(tv1, tv2) <= 0)
|
||||
*tvmin = *tv1;
|
||||
else
|
||||
*tvmin = *tv2;
|
||||
/*
|
||||
* compares <tv1> and <tv2> : returns 1 if <tv1> is before <tv2>, otherwise 0.
|
||||
* This should be very fast because it's used in schedulers.
|
||||
* It has been optimized to return 1 (so call it in a loop which continues
|
||||
* as long as tv1<=tv2)
|
||||
*/
|
||||
|
||||
return tvmin;
|
||||
}
|
||||
#define tv_isbefore(tv1, tv2) \
|
||||
(unlikely((unsigned)(tv1)->tv_sec < (unsigned)(tv2)->tv_sec) ? 1 : \
|
||||
(unlikely((unsigned)(tv1)->tv_sec > (unsigned)(tv2)->tv_sec) ? 0 : \
|
||||
unlikely((unsigned)(tv1)->tv_usec < (unsigned)(tv2)->tv_usec)))
|
||||
|
||||
/*
|
||||
* returns the first event between <tv1> and <tv2> into <tvmin>.
|
||||
* a zero tv is ignored. <tvmin> is returned. If <tvmin> is known
|
||||
* to be the same as <tv1> or <tv2>, it is recommended to use
|
||||
* tv_bound instead.
|
||||
*/
|
||||
#define tv_min(tvmin, tv1, tv2) ({ \
|
||||
if (tv_isbefore(tv1, tv2)) { \
|
||||
*tvmin = *tv1; \
|
||||
} \
|
||||
else { \
|
||||
*tvmin = *tv2; \
|
||||
} \
|
||||
tvmin; \
|
||||
})
|
||||
|
||||
/*
|
||||
* returns the first event between <tv1> and <tv2> into <tvmin>.
|
||||
* a zero tv is ignored. <tvmin> is returned. This function has been
|
||||
* optimized to be called as tv_min(a,a,b) or tv_min(b,a,b).
|
||||
*/
|
||||
#define tv_bound(tv1, tv2) ({ \
|
||||
if (tv_isbefore(tv2, tv1)) \
|
||||
*tv1 = *tv2; \
|
||||
tv1; \
|
||||
})
|
||||
|
||||
|
||||
#endif /* _COMMON_TIME_H */
|
||||
|
@ -524,7 +524,6 @@ static http_meth_t find_http_meth(const char *str, const int len)
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Processes the client and server jobs of a session task, then
|
||||
* puts it back to the wait queue in a clean state, or
|
||||
* cleans up its resources if it must be deleted. Returns
|
||||
@ -546,14 +545,14 @@ int process_session(struct task *t)
|
||||
} while (fsm_resync);
|
||||
|
||||
if (s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE) {
|
||||
struct timeval min1, min2;
|
||||
s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||
s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
|
||||
|
||||
tv_min(&min1, &s->req->rex, &s->req->wex);
|
||||
tv_min(&min2, &s->rep->rex, &s->rep->wex);
|
||||
tv_min(&min1, &min1, &s->req->cex);
|
||||
tv_min(&t->expire, &min1, &min2);
|
||||
t->expire = s->req->rex;
|
||||
tv_min(&t->expire, &s->req->rex, &s->req->wex);
|
||||
tv_bound(&t->expire, &s->req->cex);
|
||||
tv_bound(&t->expire, &s->rep->rex);
|
||||
tv_bound(&t->expire, &s->rep->wex);
|
||||
|
||||
/* restore t to its place in the task list */
|
||||
task_queue(t);
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
#include <common/config.h>
|
||||
#include <common/mini-clist.h>
|
||||
#include <common/time.h>
|
||||
#include <common/standard.h>
|
||||
#include <common/time.h>
|
||||
|
||||
#include <proto/task.h>
|
||||
#include <types/task.h>
|
||||
@ -106,7 +106,7 @@ int wake_expired_tasks()
|
||||
tree64_foreach(&timer_wq, data, stack, slen) {
|
||||
task = LIST_ELEM(data, struct task *, qlist);
|
||||
|
||||
if (unlikely(tv_cmp_ge(&task->expire, &now) > 0)) {
|
||||
if (!tv_isbefore(&task->expire, &now)) {
|
||||
next_time = tv_remain(&now, &task->expire);
|
||||
break;
|
||||
}
|
||||
|
69
src/time.c
69
src/time.c
@ -41,19 +41,21 @@ REGPRM3 struct timeval *tv_delayfrom(struct timeval *tv, const struct timeval *f
|
||||
*/
|
||||
REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
if (tv1->tv_sec == tv2->tv_sec) {
|
||||
if (tv2->tv_usec >= tv1->tv_usec + 1000)
|
||||
if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
|
||||
if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
|
||||
return -1;
|
||||
else if (tv1->tv_usec >= tv2->tv_usec + 1000)
|
||||
else if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
|
||||
((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
|
||||
else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
|
||||
(((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
|
||||
((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
|
||||
return -1;
|
||||
else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
|
||||
((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
|
||||
else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
|
||||
(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
|
||||
((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@ -61,45 +63,32 @@ REGPRM2 int tv_cmp_ms(const struct timeval *tv1, const struct timeval *tv2)
|
||||
|
||||
/*
|
||||
* compares <tv1> and <tv2> : returns 0 if tv1 < tv2, 1 if tv1 >= tv2,
|
||||
* considering that 0 is the eternity.
|
||||
* assuming that TV_ETERNITY is greater than everything.
|
||||
*/
|
||||
REGPRM2 int tv_cmp_ge2(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
if (unlikely(tv_iseternity(tv1)))
|
||||
if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
|
||||
return 1;
|
||||
if (unlikely(tv_iseternity(tv2)))
|
||||
return 0; /* same */
|
||||
|
||||
if (tv1->tv_sec > tv2->tv_sec)
|
||||
return 1;
|
||||
if (tv1->tv_sec < tv2->tv_sec)
|
||||
if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
|
||||
return 0;
|
||||
if (tv1->tv_usec >= tv2->tv_usec)
|
||||
if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* compares <tv1> and <tv2> : returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
|
||||
* considering that 0 is the eternity.
|
||||
* assuming that TV_ETERNITY is greater than everything.
|
||||
*/
|
||||
REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
if (unlikely(tv_iseternity(tv1)))
|
||||
if (unlikely(tv_iseternity(tv2)))
|
||||
return 0; /* same */
|
||||
else
|
||||
return 1; /* tv1 later than tv2 */
|
||||
else if (likely(tv_iseternity(tv2)))
|
||||
return -1; /* tv2 later than tv1 */
|
||||
|
||||
if (tv1->tv_sec > tv2->tv_sec)
|
||||
if ((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec)
|
||||
return 1;
|
||||
else if (tv1->tv_sec < tv2->tv_sec)
|
||||
else if ((unsigned)tv1->tv_sec < (unsigned)tv2->tv_sec)
|
||||
return -1;
|
||||
else if (tv1->tv_usec > tv2->tv_usec)
|
||||
else if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
|
||||
return 1;
|
||||
else if (tv1->tv_usec < tv2->tv_usec)
|
||||
else if ((unsigned)tv1->tv_usec < (unsigned)tv2->tv_usec)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
@ -107,7 +96,7 @@ REGPRM2 int tv_cmp2(const struct timeval *tv1, const struct timeval *tv2)
|
||||
|
||||
/*
|
||||
* compares <tv1> and <tv2> modulo 1 ms: returns 0 if equal, -1 if tv1 < tv2, 1 if tv1 > tv2,
|
||||
* considering that 0 is the eternity.
|
||||
* assuming that TV_ETERNITY is greater than everything.
|
||||
*/
|
||||
REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
|
||||
{
|
||||
@ -119,19 +108,21 @@ REGPRM2 int tv_cmp2_ms(const struct timeval *tv1, const struct timeval *tv2)
|
||||
else if (tv_iseternity(tv2))
|
||||
return -1; /* tv2 later than tv1 */
|
||||
|
||||
if (tv1->tv_sec == tv2->tv_sec) {
|
||||
if (tv1->tv_usec >= tv2->tv_usec + 1000)
|
||||
if ((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec) {
|
||||
if ((unsigned)tv1->tv_usec >= (unsigned)tv2->tv_usec + 1000)
|
||||
return 1;
|
||||
else if (tv2->tv_usec >= tv1->tv_usec + 1000)
|
||||
else if ((unsigned)tv2->tv_usec >= (unsigned)tv1->tv_usec + 1000)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else if ((tv1->tv_sec > tv2->tv_sec + 1) ||
|
||||
((tv1->tv_sec == tv2->tv_sec + 1) && (tv1->tv_usec + 1000000 >= tv2->tv_usec + 1000)))
|
||||
else if (((unsigned)tv1->tv_sec > (unsigned)tv2->tv_sec + 1) ||
|
||||
(((unsigned)tv1->tv_sec == (unsigned)tv2->tv_sec + 1) &&
|
||||
((unsigned)tv1->tv_usec + 1000000 >= (unsigned)tv2->tv_usec + 1000)))
|
||||
return 1;
|
||||
else if ((tv2->tv_sec > tv1->tv_sec + 1) ||
|
||||
((tv2->tv_sec == tv1->tv_sec + 1) && (tv2->tv_usec + 1000000 >= tv1->tv_usec + 1000)))
|
||||
else if (((unsigned)tv2->tv_sec > (unsigned)tv1->tv_sec + 1) ||
|
||||
(((unsigned)tv2->tv_sec == (unsigned)tv1->tv_sec + 1) &&
|
||||
((unsigned)tv2->tv_usec + 1000000 >= (unsigned)tv1->tv_usec + 1000)))
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
@ -153,7 +144,7 @@ REGPRM2 unsigned long tv_remain2(const struct timeval *tv1, const struct timeval
|
||||
return 0; /* event elapsed */
|
||||
|
||||
ret = (tv2->tv_sec - tv1->tv_sec) * 1000;
|
||||
if (tv2->tv_usec > tv1->tv_usec)
|
||||
if ((unsigned)tv2->tv_usec > (unsigned)tv1->tv_usec)
|
||||
ret += (tv2->tv_usec - tv1->tv_usec) / 1000;
|
||||
else
|
||||
ret -= (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
@ -180,7 +171,7 @@ REGPRM2 unsigned long tv_delta(const struct timeval *tv1, const struct timeval *
|
||||
tv2 = tmp;
|
||||
}
|
||||
ret = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
if (tv1->tv_usec > tv2->tv_usec)
|
||||
if ((unsigned)tv1->tv_usec > (unsigned)tv2->tv_usec)
|
||||
ret += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
else
|
||||
ret -= (tv2->tv_usec - tv1->tv_usec) / 1000;
|
||||
|
Loading…
Reference in New Issue
Block a user