コード例 #1
0
ファイル: instrument.c プロジェクト: LJoNe/gpdb
/* Exit from a plan node */
void
InstrStopNode(Instrumentation *instr, double nTuples)
{
	instr_time	endtime;

	/* count the returned tuples */
	instr->tuplecount += nTuples;

	if (INSTR_TIME_IS_ZERO(instr->starttime))
	{
		elog(DEBUG2, "InstrStopNode called without start");
		return;
	}

	INSTR_TIME_SET_CURRENT(endtime);
	INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime);

	/* Is this the first tuple of this cycle? */
	if (!instr->running)
	{
		instr->running = true;
		instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
		/* CDB: save this start time as the first start */
		instr->firststart = instr->starttime;
	}

	INSTR_TIME_SET_ZERO(instr->starttime);
}
コード例 #2
0
ファイル: instrument.c プロジェクト: Epictetus/postgres
/* Exit from a plan node */
void
InstrStopNode(Instrumentation *instr, double nTuples)
{
	instr_time	endtime;

	/* count the returned tuples */
	instr->tuplecount += nTuples;

	if (INSTR_TIME_IS_ZERO(instr->starttime))
	{
		elog(DEBUG2, "InstrStopNode called without start");
		return;
	}

	INSTR_TIME_SET_CURRENT(endtime);
	INSTR_TIME_ACCUM_DIFF(instr->counter, endtime, instr->starttime);

	INSTR_TIME_SET_ZERO(instr->starttime);

	/* Add delta of buffer usage since entry to node's totals */
	if (instr->need_bufusage)
		BufferUsageAccumDiff(&instr->bufusage,
							 &pgBufferUsage, &instr->bufusage_start);

	/* Is this the first tuple of this cycle? */
	if (!instr->running)
	{
		instr->running = true;
		instr->firsttuple = INSTR_TIME_GET_DOUBLE(instr->counter);
	}
}
コード例 #3
0
ファイル: call_graph.c プロジェクト: postsql/call_graph
static void
call_graph_fmgr_hook(FmgrHookEventType event,
			  FmgrInfo *flinfo, Datum *args)
{
	bool aborted = false;
	EdgeHashKey key;
	EdgeHashElem *elem;
	instr_time current_time;

	if (next_fmgr_hook)
		(*next_fmgr_hook) (event, flinfo, args);

	INSTR_TIME_SET_CURRENT(current_time);

	switch (event)
	{
		case FHET_START:
		{
			bool found;

			if (call_stack == NIL)
			{
				top_level_function_oid = flinfo->fn_oid;

				/* We're about to enter the top level function; check whether we've been disabled */
				if (!enable_call_graph)
				{
					tracking_current_graph = false;
					recursion_depth = 1;
					return;
				}

				/* Start tracking the call graph; we need to create the hash table */
				create_edge_hash_table();
				tracking_current_graph = true;

				/* If we're tracking table usage, take a stat snapshot now */
				if (track_table_usage)
					table_stat_snapshot = get_table_stat_snapshot();

				/* Use InvalidOid for the imaginary edge into the top level function */
				key.caller = InvalidOid;
			}
			else
			{
				if (!tracking_current_graph)
				{
					/*
					 * Not tracking this graph, just see whether we've recursed into the top level function
					 * (see the comments near the beginning of the file)
					 */
					if (flinfo->fn_oid == top_level_function_oid)
						recursion_depth++;

					return;
				}

				elem = linitial(call_stack);

				/* Calculate the self time we spent in the previous function (elem->key.callee in this case). */
				INSTR_TIME_ACCUM_DIFF(elem->self_time, current_time, current_self_time_start);

				key.caller = elem->key.callee;
			}

			key.callee = flinfo->fn_oid;

			elem = hash_search(edge_hash_table, (void *) &key, HASH_ENTER, &found);
			if (found)
				elem->num_calls++;
			else
			{
				elem->key = key;
				elem->num_calls = 1;
				INSTR_TIME_SET_ZERO(elem->total_time);
				INSTR_TIME_SET_ZERO(elem->self_time);
			}

			call_stack = lcons(elem, call_stack);

			INSTR_TIME_SET_CURRENT(elem->total_time_start);
			memcpy(&current_self_time_start, &elem->total_time_start, sizeof(instr_time));
		}
			break;

		/*
		 * In both ABORT and END cases we pop off the last element from the call stack, and if the stack
		 * is empty, we process the data we gathered.
		 *
		 * XXX for some reason if the top level function aborted SPI won't work correctly.
		 */
		case FHET_ABORT:
			aborted = true;

		case FHET_END:
			/*
			 * If we're not tracking this particular graph, we only need to see whether we're done
			 * with the graph or not.
			 */
			if (!tracking_current_graph)
			{
				if (top_level_function_oid == flinfo->fn_oid)
				{
					recursion_depth--;
					if (recursion_depth == 0)
						top_level_function_oid = InvalidOid;
				}

				Assert(table_stat_snapshot == NULL);
				return;
			}

			Assert(((EdgeHashElem *) linitial(call_stack))->key.callee == flinfo->fn_oid);

			elem = linitial(call_stack);
			INSTR_TIME_ACCUM_DIFF(elem->self_time, current_time, current_self_time_start);
			INSTR_TIME_ACCUM_DIFF(elem->total_time, current_time, elem->total_time_start);

			call_stack = list_delete_first(call_stack);

			if (call_stack != NIL)
			{
				/* we're going back to the previous node, start recording its self_time */
				INSTR_TIME_SET_CURRENT(current_self_time_start);
				break;
			}

			/*
			 * At this point we're done with the graph.  If the top level function exited cleanly, we can
			 * process the data we've gathered in the hash table and add that data into the buffer table.
			 */
			if (!aborted)
			{
				/*
				 * It is in some cases possible that process_edge_data() throws an exception.  We really need to
				 * clean up our state in case that happens.
				 */
				PG_TRY();
				{
					Datum buffer_id = assign_callgraph_buffer_id();

					/* Better check both conditions here */
					if (table_stat_snapshot && track_table_usage)
						insert_snapshot_delta(buffer_id, table_stat_snapshot);

					process_edge_data(buffer_id);
				}
				PG_CATCH();
				{
					if (table_stat_snapshot)
					{
						release_table_stat_snapshot(table_stat_snapshot);
						table_stat_snapshot = NULL;
					}

					destroy_edge_hash_table();
					top_level_function_oid = InvalidOid;
					PG_RE_THROW();
				}
				PG_END_TRY();
			}

			if (table_stat_snapshot)
			{
				release_table_stat_snapshot(table_stat_snapshot);
				table_stat_snapshot = NULL;
			}

			destroy_edge_hash_table();
			top_level_function_oid = InvalidOid;

			break;
		default:
			elog(ERROR, "Unknown FmgrHookEventType %d", event);
			return;
	}
}