Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Analyses for DPDK Applications Using the Ethdev Library #83

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

adel-belkhiri
Copy link
Contributor

This PR introduces 5 performance analyses for DPDK applications implemented using the ethdev library. These analyses provide insights into packet distribution, rate, throughput, and PMD thread busyness, thus helping monitor and optimize application performance.

New Features:

  1. Packet Rate Analysis:
    Computes the packet rate (in pps) for transmitted and received Ethernet traffic on a per-queue basis. It helps monitor the efficiency of traffic processing by calculating the number of packets received or transmitted in a given period.

  2. Packet Throughput Analysis:
    Analyzes packet throughput (in bps) for transmitted and received Ethernet traffic. This is done on a per-queue basis to evaluate bandwidth usage.

  3. Busyness Analysis for PMD Threads:
    Estimates how busy PMD threads are by comparing the times they successfully retrieve packets from the NIC queue versus when they are merely spinning without processing any packets. This can be used to evaluate the efficiency of polling operations.

  4. Packet Distribution Analysis:
    Analyzes the distribution of packets retrieved in a single rte_eth_rx_burst() call, on a per-thread and per-queue basis. This analysis provides insights into packet retrieval patterns, including how evenly or unevenly the workload is distributed across queues.

  5. Packet Distribution Statistics:
    Computes various statistics related to packet retrieval distribution, including the minimum, maximum, average, and standard deviation for packets retrieved in a single rte_eth_rx_burst() call, which offers more granular visibility into traffic distribution patterns.

Copy link
Contributor

@MatthewKhouzam MatthewKhouzam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor changes.

* @author Adel Belkhiri
*/
@SuppressWarnings({ "nls" })
public interface Attributes {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend renaming to EthAttributes or something more descriptive

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments Matthew. I renamed it as suggested in the new version.

*
* @author Adel Belkhiri
*/
@SuppressWarnings({ "nls" })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NonNullByDefault

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

try {
StateSystemBuilderUtils.incrementAttributeLong(ssb, ts, queueQuark, nbPkts);
} catch (StateValueTypeException e) {
Activator.getInstance().logWarning(getClass().getName() + ": problem accessing the state of a NIC queue (Quark =" + String.valueOf(queueQuark) + ")"); //$NON-NLS-1$ //$NON-NLS-2$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this... can you put it in the activator to have it everywhere?

* @param ts
* time to use for state change
*/
static private void createNicQueue(ITmfStateSystemBuilder ssb, int queueSetQuark, int nbQueues, long ts) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createNicQueues

updateCounts(ssb, rxQueueQark, Objects.requireNonNull(nbRxPkts), ts);

} else if (eventName.equals(DpdkEthdevEventLayout.eventEthdevTxqBurst())) {
Integer queueId = event.getContent().getFieldValue(Integer.class, DpdkEthdevEventLayout.fieldQueueId());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put in a common helper function, you have it for 100-103 and 108-110

@@ -0,0 +1,109 @@
package org.eclipse.tracecompass.incubator.internal.dpdk.core.ethdev.rate.analysis;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyright header

// Event field names
// ------------------------------------------------------------------------

/**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs a description too

i++;
}
} catch (IndexOutOfBoundsException e) {
Activator.getInstance().logWarning("A DPDK event (" + DpdkEthdevEventLayout.eventEthdevConfigure() + ") is missing"); //$NON-NLS-1$ //$NON-NLS-2$
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

write the index? or just log the exception.

*
* @author Geneviève Bastien
*/
public class IODataPalette {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reuse for the win!

@arfio arfio self-requested a review September 27, 2024 19:04
Copy link
Contributor

@arfio arfio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think all the analyses look very interesting but there is a lot of duplicated that can easily be reused throughout. In particular the throughput and rate analysis that are very similar, it could be merged into one analysis with multiple views.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is duplicated throughout the different packages you created. You should only have one version of this file. Also it is missing a copyright header

Copy link
Contributor Author

@adel-belkhiri adel-belkhiri Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Arnauld for the feedback. I have a question: should I just change the name of the file/class for each analysis (example: DpdkEthdevThroughputEventLayout.java), or combine all these files into one single layout class used by all the analyses for Ethdev?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not adding this file to the trace package, and adding it to the DpdkTrace aspects as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all the aspects in the ethdev poll analyses into regular classes. It turns out that aspects are not required for this type of analysis.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not merging this analysis and the throughput one ? Both uses 99% the same code, you could merge both and just use 2 different data providers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment Arnaud. Indeed, I merged the throughput and rate analyses, thus, reducing much the duplicated code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


}
} catch (TimeRangeException | AttributeNotFoundException | StateSystemDisposedException e) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs at least a warning or something.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could have a parent class for this to reuse most of the code.

@adel-belkhiri adel-belkhiri force-pushed the dpdk-ethdev branch 2 times, most recently from 0b9fd6f to d2f9125 Compare October 16, 2024 15:54
Copy link
Contributor

@MatthewKhouzam MatthewKhouzam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small changes needed

return nodes;
}

@Override
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this?

Copy link
Contributor Author

@adel-belkhiri adel-belkhiri Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @MatthewKhouzam for this comment. Omitting the "@OverRide" annotation results in an error, so I believe we still need it.

/**
* Abstract class for building data series illustrating DPDK NICs throughput.
*/
protected abstract class AbstractNicQueueBuilder {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I put this class in a separate file and changed its visibility to "package".

return stateValue instanceof Number ? ((Number) stateValue).doubleValue() : 0.0;
} catch (AttributeNotFoundException | IndexOutOfBoundsException e) {
Activator.getInstance().logError("Error accessing packets size on state system", e); //$NON-NLS-1$
return 0.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be NaN or 0.0? asking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatthewKhouzam: You are right! thanks.

return stateValue instanceof Number ? ((Number) stateValue).doubleValue() : 0.0;
} catch (AttributeNotFoundException | IndexOutOfBoundsException e) {
Activator.getInstance().logError("Error accessing packets count on state system", e); //$NON-NLS-1$
return 0.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}

private Messages() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a //does nothing here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}

private Messages() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@Override
protected ITmfTreeColumnDataProvider getColumnDataProvider() {
return () -> {
return ImmutableList.of(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get away with List.of?

Copy link
Contributor Author

@adel-belkhiri adel-belkhiri Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MatthewKhouzam: Yes, we can replace ImmutableList.of() with List.of(). I checked and found that List.of() was introduced in Java 9, making it a suitable replacement here. Thank you for the comment!

NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}

private Messages() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//do nothing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@arfio arfio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of small comments, once they are fixed, I will be happy to approve !

@@ -15,8 +15,12 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.tracecompass.tmf.core,
org.eclipse.tracecompass.tmf.ctf.core,
org.eclipse.tracecompass.analysis.os.linux.core,
org.eclipse.jdt.annotation;bundle-version="2.2.400"
org.eclipse.jdt.annotation;bundle-version="2.2.400",
com.google.guava,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be set in Imported packages.

@Override
public boolean canExecute(ITmfTrace trace) {
if (trace instanceof DpdkTrace) {
return ((DpdkTrace) trace).validate(null, trace.getPath()).isOK() ? true : false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use a ternary operator there, you can just return the result from isOk().

@@ -15,8 +15,12 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.tracecompass.tmf.core,
org.eclipse.tracecompass.tmf.ctf.core,
org.eclipse.tracecompass.analysis.os.linux.core,
org.eclipse.jdt.annotation;bundle-version="2.2.400"
com.google.guava,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be in the imported packages section.

org.eclipse.jdt.annotation;bundle-version="2.2.400"
com.google.guava,
org.eclipse.jdt.annotation;bundle-version="2.2.400",
org.eclipse.tracecompass.analysis.lami.core
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be above the org.eclipse.jdt.annotation;bundle-version="2.2.400" line to make a clearer diff.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should maybe be in org.eclipse.tracecompass.incubator.internal.dpdk.core.ethdev

prevTime = time;
}

return ImmutableList.copyOf(Iterables.transform(builders, builder -> builder.build(Y_AXIS_DESCRIPTION)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unchecked conversion warning


for (Entry<Long, Integer> entry : getSelectedEntries(filter).entrySet()) {
long id = entry.getKey();
int quark = entry.getValue();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two unsafe interpretation, the getKey() and getValue() should be put in a Objects.requireNonNull().

return new AbstractSelectTreeViewer2(parent, 1, DpdkEthdevSpinDataProvider.ID) {
@Override
protected ITmfTreeColumnDataProvider getColumnDataProvider() {
return () -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curly braces should be removed, List.of should be changed to ImmutableList to fix the warning

return new AbstractSelectTreeViewer2(parent, 1, DpdkEthdevThroughputBpsDataProvider.ID) {
@Override
protected ITmfTreeColumnDataProvider getColumnDataProvider() {
return () -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment.

return new AbstractSelectTreeViewer2(parent, 1, DpdkEthdevThroughputPpsDataProvider.ID) {
@Override
protected ITmfTreeColumnDataProvider getColumnDataProvider() {
return () -> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment

Introduces packet throughput analysis for DPDK applications
using the ethdev library. The analysis calculates packet throughput in
both bits per second (bps) and packets per second (pps) for transmitted
and received Ethernet traffic on a per-queue basis.

Note that the calculation of throughput in bps requires the existence of
custom profiling events in the trace

Signed-off-by: Adel Belkhiri <[email protected]>
PMD threads continuously poll NIC queues, leading to constant 100% CPU usage.
This analysis provides a rough estimation of how busy PMD threads are with
actual work, by comparing the times they successfully retrieve packets from the
NIC queue versus the times they are merely spinning without processing any
packets.

Signed-off-by: Adel Belkhiri <[email protected]>
Introduce packet distribution analysis for PMD threads based on ethdev library.
This analysis computes the distribution of packets retrieved in a single
rte_eth_rx_burst() call, on a per-queue basis.

Signed-off-by: Adel Belkhiri <[email protected]>
Introduce packet distribution statistics analysis for PMD threads in the ethdev
library. This analysis calculates various statistics related to the
distribution of packets retrieved in a single rte_eth_rx_burst() call, on a
per-thread and per-queue basis. The computed statistics include the minimum,
maximum, average number of packets retrieved, as well as the standard deviation.

Signed-off-by: Adel Belkhiri <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants