mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-30 00:00:16 +01:00
introduce lws_latency
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
3b228c5470
commit
d636e35c2b
6 changed files with 112 additions and 5 deletions
|
@ -98,6 +98,12 @@ There are several other possible configure options
|
||||||
the code / data size / speed improvements may be
|
the code / data size / speed improvements may be
|
||||||
critical.
|
critical.
|
||||||
|
|
||||||
|
--with-latency Builds the latency-tracking code into the library...
|
||||||
|
this slows your library down a bit but is very useful
|
||||||
|
to find the cause of unexpected latencies occurring
|
||||||
|
inside the library. See README.test-apps for more
|
||||||
|
info
|
||||||
|
|
||||||
|
|
||||||
Externally configurable important constants
|
Externally configurable important constants
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
|
@ -215,6 +215,7 @@ available are (OR together the numbers to select multiple)
|
||||||
64 HEADER
|
64 HEADER
|
||||||
128 EXTENSION
|
128 EXTENSION
|
||||||
256 CLIENT
|
256 CLIENT
|
||||||
|
512 LATENCY
|
||||||
|
|
||||||
|
|
||||||
Websocket version supported
|
Websocket version supported
|
||||||
|
@ -224,3 +225,26 @@ The final IETF standard is supported for both client and server, protocol
|
||||||
version 13.
|
version 13.
|
||||||
|
|
||||||
|
|
||||||
|
Latency Tracking
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Since libwebsockets runs using poll() and a single threaded approach, any
|
||||||
|
unexpected latency coming from system calls would be bad news. There's now
|
||||||
|
a latency tracking scheme that can be built in with --with-latency at
|
||||||
|
configure-time, logging the time taken for system calls to complete and if
|
||||||
|
the whole action did complete that time or was deferred.
|
||||||
|
|
||||||
|
You can see the detailed data by enabling logging level 512 (eg, -d 519 on
|
||||||
|
the test server to see that and the usual logs), however even without that
|
||||||
|
the "worst" latency is kept and reported to the logs with NOTICE severity
|
||||||
|
when the context is destroyed.
|
||||||
|
|
||||||
|
Some care is needed interpreting them, if the action completed the first figure
|
||||||
|
(in us) is the time taken for the whole action, which may have retried through
|
||||||
|
the poll loop many times and will depend on network roundtrip times. High
|
||||||
|
figures here don't indicate a problem. The figure in us reported after "lat"
|
||||||
|
in the logging is the time taken by this particular attempt. High figures
|
||||||
|
here may indicate a problem, or if you system is loaded with another app at
|
||||||
|
that time, such as the browser, it may simply indicate the OS gave preferential
|
||||||
|
treatment to the other app during that call.
|
||||||
|
|
||||||
|
|
13
configure.ac
13
configure.ac
|
@ -94,6 +94,19 @@ CFLAGS="$CFLAGS -DLWS_NO_EXTENSIONS"
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL(NO_EXTENSIONS, test x$no_extensions = xyes)
|
AM_CONDITIONAL(NO_EXTENSIONS, test x$no_extensions = xyes)
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
AC_ARG_WITH(latency,
|
||||||
|
[ --with-latency Build latency measuring code into the library ],
|
||||||
|
[ latency=yes
|
||||||
|
])
|
||||||
|
|
||||||
|
if test "x$latency" = "xyes" ; then
|
||||||
|
CFLAGS="$CFLAGS -DLWS_LATENCY"
|
||||||
|
fi
|
||||||
|
AM_CONDITIONAL(LATENCY, test x$latency = xyes)
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
|
@ -63,6 +63,7 @@ static const char *log_level_names[] = {
|
||||||
"HEADER",
|
"HEADER",
|
||||||
"EXTENSION",
|
"EXTENSION",
|
||||||
"CLIENT",
|
"CLIENT",
|
||||||
|
"LATENCY",
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -929,6 +930,11 @@ libwebsocket_context_destroy(struct libwebsocket_context *context)
|
||||||
int m;
|
int m;
|
||||||
struct libwebsocket_extension *ext;
|
struct libwebsocket_extension *ext;
|
||||||
|
|
||||||
|
#ifdef LWS_LATENCY
|
||||||
|
if (context->worst_latency_info[0])
|
||||||
|
lwsl_notice("Worst latency: %s\n", context->worst_latency_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (n = 0; n < context->fds_count; n++) {
|
for (n = 0; n < context->fds_count; n++) {
|
||||||
struct libwebsocket *wsi = context->lws_lookup[context->fds[n].fd];
|
struct libwebsocket *wsi = context->lws_lookup[context->fds[n].fd];
|
||||||
libwebsocket_close_and_free_session(context,
|
libwebsocket_close_and_free_session(context,
|
||||||
|
@ -1207,6 +1213,40 @@ libwebsocket_get_socket_fd(struct libwebsocket *wsi)
|
||||||
return wsi->sock;
|
return wsi->sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LWS_LATENCY
|
||||||
|
void
|
||||||
|
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completed)
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
unsigned long u;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
|
u = (tv.tv_sec * 1000000) + tv.tv_usec;
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
if (completed) {
|
||||||
|
if (wsi->action_start == wsi->latency_start)
|
||||||
|
sprintf(buf, "Completion first try lat %luus: %p: ret %d: %s\n", u - wsi->latency_start, (void *)wsi, ret, action);
|
||||||
|
else
|
||||||
|
sprintf(buf, "Completion %luus: lat %luus: %p: ret %d: %s\n", u - wsi->action_start, u - wsi->latency_start, (void *)wsi, ret, action);
|
||||||
|
wsi->action_start = 0;
|
||||||
|
} else
|
||||||
|
sprintf(buf, "lat %luus: %p: ret %d: %s\n", u - wsi->latency_start, (void *)wsi, ret, action);
|
||||||
|
if (u - wsi->latency_start > context->worst_latency) {
|
||||||
|
context->worst_latency = u - wsi->latency_start;
|
||||||
|
strcpy(context->worst_latency_info, buf);
|
||||||
|
}
|
||||||
|
lwsl_latency("%s", buf);
|
||||||
|
} else {
|
||||||
|
wsi->latency_start = u;
|
||||||
|
if (!wsi->action_start)
|
||||||
|
wsi->action_start = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LWS_NO_SERVER
|
#ifdef LWS_NO_SERVER
|
||||||
int
|
int
|
||||||
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
|
_libwebsocket_rx_flow_control(struct libwebsocket *wsi)
|
||||||
|
|
|
@ -76,38 +76,44 @@ enum lws_log_levels {
|
||||||
LLL_HEADER = 1 << 6,
|
LLL_HEADER = 1 << 6,
|
||||||
LLL_EXT = 1 << 7,
|
LLL_EXT = 1 << 7,
|
||||||
LLL_CLIENT = 1 << 8,
|
LLL_CLIENT = 1 << 8,
|
||||||
|
LLL_LATENCY = 1 << 9,
|
||||||
|
|
||||||
LLL_COUNT = 9 /* set to count of valid flags */
|
LLL_COUNT = 10 /* set to count of valid flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void _lws_log(int filter, const char *format, ...);
|
extern void _lws_log(int filter, const char *format, ...);
|
||||||
|
|
||||||
/* warn and log are always compiled in */
|
/* notice, warn and log are always compiled in */
|
||||||
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
|
#define lwsl_notice(...) _lws_log(LLL_NOTICE, __VA_ARGS__)
|
||||||
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
|
#define lwsl_warn(...) _lws_log(LLL_WARN, __VA_ARGS__)
|
||||||
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
|
#define lwsl_err(...) _lws_log(LLL_ERR, __VA_ARGS__)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* weaker logging can be deselected at configure time using disable_debug
|
* weaker logging can be deselected at configure time using --disable-debug
|
||||||
* that gets rid of the overhead of checking while keeping _warn and _err
|
* that gets rid of the overhead of checking while keeping _warn and _err
|
||||||
* active
|
* active
|
||||||
*/
|
*/
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|
||||||
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
|
#define lwsl_info(...) _lws_log(LLL_INFO, __VA_ARGS__)
|
||||||
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
|
#define lwsl_debug(...) _lws_log(LLL_DEBUG, __VA_ARGS__)
|
||||||
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
|
#define lwsl_parser(...) _lws_log(LLL_PARSER, __VA_ARGS__)
|
||||||
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
|
#define lwsl_header(...) _lws_log(LLL_HEADER, __VA_ARGS__)
|
||||||
#define lwsl_ext(...) _lws_log(LLL_HEADER, __VA_ARGS__)
|
#define lwsl_ext(...) _lws_log(LLL_EXT, __VA_ARGS__)
|
||||||
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
|
#define lwsl_client(...) _lws_log(LLL_CLIENT, __VA_ARGS__)
|
||||||
|
#define lwsl_latency(...) _lws_log(LLL_LATENCY, __VA_ARGS__)
|
||||||
extern void lwsl_hexdump(void *buf, size_t len);
|
extern void lwsl_hexdump(void *buf, size_t len);
|
||||||
|
|
||||||
#else /* no debug */
|
#else /* no debug */
|
||||||
|
|
||||||
#define lwsl_info(...)
|
#define lwsl_info(...)
|
||||||
#define lwsl_debug(...)
|
#define lwsl_debug(...)
|
||||||
#define lwsl_parser(...)
|
#define lwsl_parser(...)
|
||||||
#define lwsl_header(...)
|
#define lwsl_header(...)
|
||||||
#define lwsl_ext(...)
|
#define lwsl_ext(...)
|
||||||
#define lwsl_client(...)
|
#define lwsl_client(...)
|
||||||
|
#define lwsl_latency(...)
|
||||||
#define lwsl_hexdump(a, b)
|
#define lwsl_hexdump(a, b)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum libwebsocket_context_options {
|
enum libwebsocket_context_options {
|
||||||
|
|
|
@ -239,6 +239,11 @@ struct libwebsocket_context {
|
||||||
int listen_service_fd;
|
int listen_service_fd;
|
||||||
int listen_service_extraseen;
|
int listen_service_extraseen;
|
||||||
|
|
||||||
|
#ifdef LWS_LATENCY
|
||||||
|
unsigned long worst_latency;
|
||||||
|
char worst_latency_info[256];
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LWS_OPENSSL_SUPPORT
|
#ifdef LWS_OPENSSL_SUPPORT
|
||||||
int use_ssl;
|
int use_ssl;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
|
@ -337,6 +342,10 @@ struct libwebsocket {
|
||||||
|
|
||||||
int sock;
|
int sock;
|
||||||
int position_in_fds_table;
|
int position_in_fds_table;
|
||||||
|
#ifdef LWS_LATENCY
|
||||||
|
unsigned long action_start;
|
||||||
|
unsigned long latency_start;
|
||||||
|
#endif
|
||||||
|
|
||||||
void *user_space;
|
void *user_space;
|
||||||
|
|
||||||
|
@ -370,6 +379,15 @@ struct libwebsocket {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef LWS_LATENCY
|
||||||
|
static inline void lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completion) { while (0); }
|
||||||
|
static inline void lws_latency_pre(struct libwebsocket_context *context, struct libwebsocket *wsi) { while (0); }
|
||||||
|
#else
|
||||||
|
#define lws_latency_pre(_context, _wsi) lws_latency(_context, _wsi, NULL, 0, 0)
|
||||||
|
extern void
|
||||||
|
lws_latency(struct libwebsocket_context *context, struct libwebsocket *wsi, const char *action, int ret, int completion);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int
|
extern int
|
||||||
libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
libwebsocket_client_rx_sm(struct libwebsocket *wsi, unsigned char c);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue