-
Notifications
You must be signed in to change notification settings - Fork 1
Channels & loaders
Channel & Loaders is a desirable feature for TSLoad 0.3 to replace threadpools an other "hackish" stuff like request schedulers and threadpool dispatchers with more flexible infrastructure involving multiple processes. It also allows to implement custom, modularized channels which would simulate real system behaviour like reacting on epoll_wait()
.
Processes are linked to TSLoad Core and have full set of its features. They also maintain service management channel, which is used to send commands from main process to them.
Their API is:
int proc_spawn(ts_proc_t* proc, tsobj_node_t* properties)
int proc_stop(ts_proc_t* proc)
int proc_send(ts_proc_t* proc, void* msg, size_t len)
Each object has to be replicated across process should be easily serializable, so it should not contain any pointers. The following objects are spawned by processes through proc_send()
call
Notable implementations include Main, Local and various implementations of Remote
Generators create requests and send them over channels to balancers or directly to loaders. They may use trace files to do that. They replace request schedulers and some features of threadpool dispatchers.
int gen_create(ts_generator_t* gen, workload_t*, tsobj_node_t* properties)
request_t* gen_generate(ts_generator_t* gen) // returns new request with filled rq_sched_time
// no sleeping allowed. Generated requests are queued by
// TSLoad, so several consequent calls may happen, but
// they may be not satisfied
int gen_acknowledge(ts_generator_t* gen, request_t* rq) // Acknowledge a request after it was
// executed by loader, so new requests
// may be generated (for Think-time)
Notable implementations are IAT, Think-time, Trace, Benchmark
Channels receive and send requests over network or locally between generators, dispatchers and loaders. They also responsible for serializing and deserializing data wherever necessary. They do not send service information (processes is responsible for that).
int chan_create_srv(ts_chan_t* chan, tsobj_node_t* props) // Create server-side connection
int chan_establish(ts_chan_t* chan) // Connect client to server may be called multiple times
int chan_send(ts_chan_t* chan, request_t* rq)
request_t* chan_receive(ts_chan_t** chan, int ccount)
ts_chan_t* chan_poll(ts_chan_t** chan, int ccount)
Notable implementations include Local which uses cv for notificatoin in chan_poll and local memory, Shared-memory, Sockets and Named pipes
Dispatchers allow to multiplex requests from N channels or generators to M loaders (through channels). They also queue requests coming from generators.
disp_add_generator(ts_disp_t* disp, ts_generator_t* gen)
disp_add_inchan(ts_disp_t* disp, ts_chan_t* in)
disp_add_outchan(ts_disp_t* disp, ts_chan_t* out)
disp_acknowledge(ts_disp_t* disp, request_t* rq)
Loaders run pre-liminary workload configuration on per-process basis, receive requests through channel(-s), execute them and send back.
loader_configure_wl(ts_loader_t* loader, workload_t* wl)
loader_run_request(ts_loader_t* loader, request_t* rq)
Notable loader: Thread
- If there is the room for new request (queue drained for queue-based dispatcher, loader acknowledged request in case of first-free dispatcher) or after polling interval,
gen_generate()
of next generator is called, orchan_recv()
called for incoming channel. If it fails (no request is present), TSLoad picks next, and so on until all array of channels/generators was processed. - If time of a request has not come, dispatcher sleeps, than sends it to loader, picking one of the outgoing channels
- Loader receives request with
chan_recv()
and if time has not come also sleeps. After that it starts executing a request. - When execution is finished, acknowledgements are sent to generator and dispatcher. Processed request is put to queue of finished requests (per-process)
- At the unspecified moment of time, main TSLoad process walks over queues of finished requests, and writes to output TSFile.