Re: [PATCH v2 15/17] libtraceeval histogram: Add traceeval_iterator_sort_custom()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 16 Aug 2023 16:57:16 -0600
Ross Zwisler <zwisler@xxxxxxxxxx> wrote:

> > +static int iter_custom_cmp(const void *A, const void *B, void *data)
> > +{
> > +	struct iter_custom_data *cust_data = data;
> > +	struct traceeval_iterator *iter = cust_data->iter;
> > +	struct traceeval *teval = iter->teval;
> > +	const struct entry *a = *((const struct entry **)A);
> > +	const struct entry *b = *((const struct entry **)B);
> > +
> > +	return cust_data->sort_fn(teval, a->keys, a->vals, b->keys, b->vals,
> > +				  cust_data->data);
> > +}
> > +
> > +int traceeval_iterator_sort_custom(struct traceeval_iterator *iter,
> > +				   traceeval_cmp_fn sort_fn, void *data)
> > +{
> > +	struct iter_custom_data cust_data = {
> > +		.iter = iter,
> > +		.sort_fn = sort_fn,
> > +		.data = data
> > +	};
> > +
> > +	qsort_r(iter->entries, iter->nr_entries, sizeof(*iter->entries),
> > +		iter_custom_cmp, &cust_data);  
> 
> I guess I don't yet see what this gives us over the existing sorting and
> iterators?  Does this do the same thing, we just pass in the sort function
> instead of calling traceeval_iterator_sort() one or more times?

This should be used in replace of the other sorting. It allows the user to
make a complex sort. If you look at the last patch, the sample uses this:

+/*
+ * Sort all the processes by the RUNNING state.
+ *  If A and B have the same COMM, then sort by state.
+ *  else
+ *    Find the RUNNNIG state for A and B
+ *    If the RUNNING state does not exist, it's considered -1
+ *  If RUNNING is equal, then sort by COMM.
+ */
+static int compare_pdata(struct traceeval *teval_data,
+				const union traceeval_data *Akeys,
+				const union traceeval_data *Avals,
+				const union traceeval_data *Bkeys,
+				const union traceeval_data *Bvals,
+				void *data)
+{
+	struct traceeval *teval = data; /* The deltas are here */
+	union traceeval_data keysA[] = {
+		{ .cstring = Akeys[0].cstring }, { .number = RUNNING } };
+	union traceeval_data keysB[] = {
+		{ .cstring = Bkeys[0].cstring }, { .number = RUNNING } };
+	struct traceeval_stat *statA;
+	struct traceeval_stat *statB;
+	unsigned long long totalA = -1;
+	unsigned long long totalB = -1;
+
+	/* First check if we are on the same task */
+	if (strcmp(Akeys[0].cstring, Bkeys[0].cstring) == 0) {
+		/* Sort decending */
+		if (Bkeys[1].number > Akeys[1].number)
+			return -1;
+		return Bkeys[1].number != Akeys[1].number;
+	}
+
+	/* Get the RUNNING values for both processes */
+	statA = traceeval_stat(teval, keysA, &delta_vals[0]);
+	if (statA)
+		totalA = traceeval_stat_total(statA);
+
+	statB = traceeval_stat(teval, keysB, &delta_vals[0]);
+	if (statB)
+		totalB = traceeval_stat_total(statB);
+
+	if (totalB < totalA)
+		return -1;
+	if (totalB > totalA)
+		return 1;
+
+	return strcmp(Bkeys[0].cstring, Akeys[0].cstring);
+}


> 
> > +
> > +	iter->needs_sort = false;  
> 
> Also probably need to set
>   iter->next = 0;

So much for redundancy!

Thanks,

-- Steve

> 
> > +	return 0;
> > +}
> > +



[Index of Archives]     [Linux USB Development]     [Linux USB Development]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux