Commit 5b822d4c authored by Vishal Verma's avatar Vishal Verma Committed by Jim Harris
Browse files

event: Add tsc stats to the reactor



This adds tsc statistics (busy, idle or unknown) to the reactor.
It will help measure actual time we are busy vs. idle during
an event run or whenever a poller kicks in.

Change-Id: Ife556a27a30dab842488bacb5fbee0d4297745c3
Signed-off-by: default avatarVishal Verma <vishal4.verma@intel.com>
Reviewed-on: https://review.gerrithub.io/412695


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 6be654aa
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -122,6 +122,12 @@ struct spdk_app_opts {
	bool			delay_subsystem_init;
};

struct spdk_reactor_tsc_stats {
	uint64_t busy_tsc;
	uint64_t idle_tsc;
	uint64_t unknown_tsc;
};

/**
 * Initialize the default value of opts
 *
@@ -277,6 +283,15 @@ void spdk_reactor_enable_context_switch_monitor(bool enabled);
 */
bool spdk_reactor_context_switch_monitor_enabled(void);

/**
 * Get tsc stats from a given reactor
 * Copy cumulative reactor tsc values to user's tsc_stats structure.
 *
 * \param tsc_stats User's tsc_stats structure.
 * \param core_id Get tsc data on this Reactor core id.
 */
int spdk_reactor_get_tsc_stats(struct spdk_reactor_tsc_stats *tsc_stats, uint32_t core_id);

#ifdef __cplusplus
}
#endif
+63 −4
Original line number Diff line number Diff line
@@ -90,6 +90,11 @@ struct spdk_reactor {
	/* Poller for get the rusage for the reactor. */
	struct spdk_poller				*rusage_poller;

	/* Reactor tsc stats */
	struct spdk_reactor_tsc_stats			tsc_stats;

	uint64_t					tsc_last;

	/* The last known rusage values */
	struct rusage					rusage;

@@ -408,6 +413,41 @@ spdk_reactor_context_switch_monitor_enabled(void)
	return g_context_switch_monitor_enabled;
}

static void
spdk_reactor_add_tsc_stats(void *arg, int rc, uint64_t now)
{
	struct spdk_reactor *reactor = arg;
	struct spdk_reactor_tsc_stats *tsc_stats = &reactor->tsc_stats;

	if (rc == 0) {
		/* Poller status idle */
		tsc_stats->idle_tsc += now - reactor->tsc_last;
	} else if (rc == 1) {
		/* Poller status busy */
		tsc_stats->busy_tsc += now - reactor->tsc_last;
	} else {
		/* Poller status unknown */
		tsc_stats->unknown_tsc += now - reactor->tsc_last;
	}

	reactor->tsc_last = now;
}

int
spdk_reactor_get_tsc_stats(struct spdk_reactor_tsc_stats *tsc_stats, uint32_t core)
{
	struct spdk_reactor *reactor;

	if (!spdk_cpuset_get_cpu(g_spdk_app_core_mask, core)) {
		return -1;
	}

	reactor = spdk_reactor_get(core);
	*tsc_stats = reactor->tsc_stats;

	return 0;
}

/**
 *
 * \brief This is the main function of the reactor thread.
@@ -438,6 +478,7 @@ _spdk_reactor_run(void *arg)
	uint64_t		idle_started, now;
	uint64_t		spin_cycles, sleep_cycles;
	uint32_t		sleep_us;
	int			rc = -1;
	char			thread_name[32];

	snprintf(thread_name, sizeof(thread_name), "reactor_%u", reactor->lcore);
@@ -456,11 +497,17 @@ _spdk_reactor_run(void *arg)
	if (g_context_switch_monitor_enabled) {
		_spdk_reactor_context_switch_monitor_start(reactor, NULL);
	}
	now = spdk_get_ticks();
	reactor->tsc_last = now;

	while (1) {
		bool took_action = false;

		event_count = _spdk_event_queue_run_batch(reactor);
		if (event_count > 0) {
			rc = 1;
			now = spdk_get_ticks();
			spdk_reactor_add_tsc_stats(reactor, rc, now);
			took_action = true;
		}

@@ -468,7 +515,9 @@ _spdk_reactor_run(void *arg)
		if (poller) {
			TAILQ_REMOVE(&reactor->active_pollers, poller, tailq);
			poller->state = SPDK_POLLER_STATE_RUNNING;
			poller->fn(poller->arg);
			rc = poller->fn(poller->arg);
			now = spdk_get_ticks();
			spdk_reactor_add_tsc_stats(reactor, rc, now);
			if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
				free(poller);
			} else {
@@ -480,17 +529,27 @@ _spdk_reactor_run(void *arg)

		poller = TAILQ_FIRST(&reactor->timer_pollers);
		if (poller) {
			if (took_action == false) {
				now = spdk_get_ticks();
			}

			if (now >= poller->next_run_tick) {
				uint64_t tmp_timer_tsc;

				TAILQ_REMOVE(&reactor->timer_pollers, poller, tailq);
				poller->state = SPDK_POLLER_STATE_RUNNING;
				poller->fn(poller->arg);
				rc = poller->fn(poller->arg);
				/* Save the tsc value from before poller->fn was executed. We want to
				 * use the current time for idle/busy tsc value accounting, but want to
				 * use the older time to reinsert to the timer poller below. */
				tmp_timer_tsc = now;
				now = spdk_get_ticks();
				spdk_reactor_add_tsc_stats(reactor, rc, now);
				if (poller->state == SPDK_POLLER_STATE_UNREGISTERED) {
					free(poller);
				} else {
					poller->state = SPDK_POLLER_STATE_WAITING;
					_spdk_poller_insert_timer(reactor, poller, now);
					_spdk_poller_insert_timer(reactor, poller, tmp_timer_tsc);
				}
				took_action = true;
			}