Workloads
TSLoad supports statically-defined userspace dynamic tracing (USDT) using etrace subsystem.
Build with --enable-usdt (Linux + SystemTap or Solaris + DTrace) or --enable-etw
(Event Tracing for Windows).
Windows:
-
Register provider with wevtutil:
C:\> wevtutil im Shared\workload.man
-
Start tracing with logman:
C:\> logman start -ets TSloadWL -p "Tslaod-Workload" 0 0 -o tracelog.etl
-
Run tsexperiment:
C:\> tsexperiment -e Data\sample\ run
-
Stop tracing:
C:\> logman stop -ets TSloadWL
-
Generate reports:
C:\> tracerpt -y tracelog.etl
-
If you need to uninstall provider, call wevtutil with um command:
C:\> wevtutil um Shared\workload.man
Linux:
root@centos# stap -e ' probe process("../lib/libtsload.so").provider("tsload__workload").mark("request__start") { println(user_string(@cast($arg1, "workload_t")->wl_name)); } ' -c 'tsexperiment -e ./var/tsload/sample run'
Solaris:
root@sol11# dtrace -n ' request-start { this->wl_name = (char*) copyin(arg0, 64); trace(stringof(this->wl_name)); }' -c 'tsexperiment -e ./var/tsload/sample run'
Constants
RQF_FINISHED, RQF_ONTIME, RQF_STARTED, RQF_SUCCESS
Request flags.
sibling of TSRequestFlag
#define RQF_STARTED 0x0001 #define RQF_SUCCESS 0x0002 #define RQF_ONTIME 0x0004 #define RQF_FINISHED 0x0008
Functions
wl_notify
public
Notify server of workload configuring progress.
done is presented in percent. If status is WLS_FAIL - it would be set to -1,
if status is WLS_SUCCESS or WLS_FINISHED - it would be set to 100
ARGUMENTS
-
wl - configuring workload
-
status - configuration/execution status
-
done - configuration progress (in percent)
-
format - message format string
LIBEXPORT void wl_notify(workload_t* wl, wl_status_t status, long progress, char* format, ...)
wl_destroy
public
wl_destroy - destroy workload
LIBEXPORT void wl_destroy(workload_t* wl)
wl_search
public
LIBEXPORT workload_t* wl_search(const char* name)
wl_unconfig, wl_config
public
LIBEXPORT void wl_config(workload_t* wl) LIBEXPORT void wl_unconfig(workload_t* wl)
wl_provide_step
Provide number of requests for current step
ARGUMENTS
-
wl - workload
-
step_id - step id to be provided
-
num_rqs - number
-
trace_rqs - linked list of trace-based request
RETURN VALUES
0 if steps are saved, -1 if incorrect step provided or wl_requests is full
int wl_provide_step(workload_t* wl, long step_id, unsigned num_rqs, list_head_t* trace_rqs)
wl_advance_step
Proceed to next step, and return number of requests in it
ARGUMENTS
-
wl - Workload to work with.
RETURN VALUES
Workload's step or NULL of no steps are on queue
workload_step_t* wl_advance_step(workload_t* wl)
wl_create_request
Create request structure, append it to requests queue, initialize
For chained workloads inherits parent step and request id
ARGUMENTS
-
wl - workload for request
-
parent - parent request (for chained workloads) For unchained workloads should be set to NULL.
request_t* wl_create_request(workload_t* wl, request_t* parent)
wl_clone_request
Clone request - used by benchmark threadpool dispatcher
request_t* wl_clone_request(request_t* origin)
wl_create_request_trace
Create trace-based requests
request_t* wl_create_request_trace(workload_t* wl, int rq_id, long step, int user_id, int thread_id,ts_time_t sched_time, void* rq_params)
wl_run_request
Run request for execution
void wl_run_request(request_t* rq)
wl_init, wl_fini
public
LIBEXPORT int wl_init(void) LIBEXPORT void wl_fini(void)
wl_rele, wl_hold
Workload reference tracker. It may be held by
- Creator
- Threadpool it attached to
- Request belongs to it
Last owner released reference frees workload,
but not until creator does that.
void wl_hold(workload_t* wl) void wl_rele(workload_t* wl)
wl_finish
Finish workload - notify that it was finished
void wl_finish(workload_t* wl)
tsobj_workload_proc, tsobj_request_format_all
public
LIBEXPORT tsobj_node_t* tsobj_request_format_all(list_head_t* rq_list) workload_t* tsobj_workload_proc(const char* wl_name, const char* wl_type, const char* tp_name, ts_time_t deadline,tsobj_node_t* wl_chain_params, tsobj_node_t* rqsched_params, tsobj_node_t* wl_params)
wl_create
wl_create - create new workload: allocate memory and initialize fields
RETURN VALUES
NULL if malloc had failed or new workload object
workload_t* wl_create(const char* name, wl_type_t* wlt, thread_pool_t* tp)
wl_destroy_impl
wl_destroy_nodetach - workload destructor
void wl_destroy_impl(workload_t* wl)
wl_chain_back
Chain workload to backwards of request chain
ARGUMENTS
-
parent - one of workloads in chain
-
wl - workload that needs to be chained
void wl_chain_back(workload_t* parent, workload_t* wl)
wl_request_destroy
Destroy request memory
void wl_request_destroy(request_t* rq)
Types
typedef struct request
Request descriptor
MEMBERS
-
rq_step - id of step to which request belongs
-
rq_id - unique id of request for workload inside step
-
rq_user_id - id of user (set by think-time scheduler)
-
rq_thread_id - id of worker in threadpool which was run this request
-
rq_sched_time - arrival time
-
rq_start_time - service begin time
-
rq_end_time - service end time
-
rq_queue_len - count of requests in worker or threadpool queue that follow this request and which arrival time is come.
-
rq_flags - request flags
-
rq_workload - workload to which it's request belongs
-
rq_params - vector of request params
-
rq_node - link node for threadpool queue
-
rq_w_node - link node for worker queue
-
rq_wl_node - link node for workload request list
-
rq_chain_next - next request (for workload chaining)
typedef struct request { long rq_step; int rq_id; int rq_user_id; int rq_thread_id; ts_time_t rq_sched_time; ts_time_t rq_start_time; ts_time_t rq_end_time; int rq_flags; int rq_queue_len; struct workload* rq_workload; void* rq_params; list_node_t rq_node; /* Next request in chain */ list_node_t rq_w_node; list_node_t rq_wl_node; struct request* rq_chain_next; /* Next request in workload chain */ } request_t;
typedef struct workload_step
typedef struct workload_step { struct workload* wls_workload; unsigned wls_rq_count; list_head_t wls_trace_rqs; } workload_step_t;
wl_status_t
Workload state
Sibling to TSWorkloadStatusCode
typedef enum { WLS_NEW = 0, WLS_CHAINED = 1, WLS_CONFIGURING = 2, WLS_CFG_FAIL = 3, WLS_CONFIGURED = 4, WLS_STARTED = 5, WLS_RUNNING = 6, WLS_FINISHED = 7, WLS_DESTROYED = 8 } wl_status_t;
typedef struct workload
Workload primary structure
Workload FSM
wl_create() -> NEW / CHAINED | cfg_thread() --> CONFIGURING / / / CONFIGURED CFG_FAIL | | STARTED | | | RUNNING-----+ | | FINISHED | | | DESTROYED <--+
MEMBERS
-
wl_name - Name of workload
-
wl_type - Reference to workload type descriptor, provided by module
-
wl_tp - Reference to thread pool it was attached. May be set to NULL for chained workloads
-
wl_params - Vector of workload parameters
-
wl_private - Private field to keep module-specific data
-
wl_cfg_thread - Thread responsible for configuration
-
wl_status - Current workload state (see FSM above)
-
wl_status_flags - Bitmap that contains workload states it was passed. Use WL_HAD_FLAGS to check it
-
wl_ref_count - Reference counter. Workload is referenced by creator and requests Because after we unconfiguring workload there are requests that was not yet reported and it is done by separate thread, we should wait for them.
-
wl_current_rq - Id of last created request
-
wl_requests - List of workload's requests. Protected by wl_rq_mutex
-
wl_start_time - Time when workload was scheduled to start
-
wl_notify_time - Timestamp when wl_notify was called. Used to reduce number of WLS_CONFIGURING messages
-
wl_start_clock - Clock when workload was run by threadpool. Used to normalize request times to start time of workload
-
wl_time - Current clock of workload: wl_start_clock + step tp_quantum
-
wl_current_step - Current step of workload
-
wl_last_step - Last step id on queue
-
wl_step_queue - Queue that contains requests number of requests (or trace-based). Protected by wl_step_mutex
-
wl_rqsched_class - Workload request scheduler
-
wl_rqsched_private - Request scheduler
typedef struct workload { AUTOSTRING char* wl_name; wl_type_t* wl_type; thread_pool_t* wl_tp; void* wl_params; void* wl_private; thread_t wl_cfg_thread; thread_mutex_t wl_status_mutex; wl_status_t wl_status; unsigned long wl_status_flags; atomic_t wl_ref_count; int wl_current_rq; thread_mutex_t wl_rq_mutex; list_head_t wl_requests; ts_time_t wl_start_time; ts_time_t wl_notify_time; ts_time_t wl_start_clock; ts_time_t wl_time; /* Requests queue */ thread_mutex_t wl_step_mutex; long wl_current_step; long wl_last_step; workload_step_t wl_step_queue[WLSTEPQSIZE]; /* End of requests queue*/ ts_time_t wl_deadline; struct workload* wl_chain_next; randgen_t* wl_chain_rg; double wl_chain_probability; struct rqsched_class* wl_rqsched_class; struct rqsched* wl_rqsched_private; struct workload* wl_hm_next; /**< next in workload hashmap*/ list_node_t wl_tp_node; /**< thread pool wl list*/ list_head_t wl_wlpgen_head; /**< per-request params*/ } workload_t;
wl_notify_msg_t
typedef struct { AUTOSTRING char* wl_name; wl_status_t status; long progress; AUTOSTRING char* msg; } wl_notify_msg_t;