Using CURL Component Data to Illustrate API Call Performance Patterns

My last post analyzed performance component results produced by the curl Internet data transfer utility in an effort to understand what typically causes slow API call performance. Four instances of unusually slow but successful calls to the World Bank Countries API were studied. In three instances (calls from Oregon, Ireland, and Japan), curl’s Processing Time metric was the primary reason the call took unusually long to complete; in the other instance (a call from Washington, DC), curl’s Resolve Time was unusually slow, leading to overall poor performance.

In addition to Resolve Time and Processing Time, curl measures the Connect Time and Transfer Time (see the post What Do Curl Timings Mean? for details).

The performance data analyzed in this series of posts was downloaded from API Science using the API Science Performance Report API. The data consists of calls to the World Bank Countries API from API Science monitors located in four global locations.

To visualize the relationship between overall API call performance and the performance of each individual curl performance component, the curl data was downloaded in JSON format. A Python program reads the JSON data into a dictionary (named perf) and creates a scatter plot where the x-axis is total performance time and the y-axis is the performance time for each curl component.

Here’s the Python code that copies data from the perf dictionary into an array that will be used for creating the plot:


    n_valid = 0
    for j in range(n_results):
        if perf['data'][j]['averageTotal']:
            comp_data[0, n_valid] = perf['data'][j]['averageResolve']
            comp_data[1, n_valid] = perf['data'][j]['averageConnect']
            comp_data[2, n_valid] = perf['data'][j]['averageProcessing']
            comp_data[3, n_valid] = perf['data'][j]['averageTransfer']
            comp_data[4, n_valid] = perf['data'][j]['averageTotal']
            n_valid = n_valid + 1

And here is the code that uses the comp_data to create a scatter plot of the week’s performance:


    x = comp_data[4][0:n_valid]  # averageTotal
    
    # create scatter plot for each component vs total time
    plt.scatter(x, comp_data[0][0:n_valid], marker='.', color='red', label='Resolve', s=3)
    plt.scatter(x, comp_data[1][0:n_valid], marker='.', color='green', label='Connect', s=3)
    plt.scatter(x, comp_data[2][0:n_valid], marker='.', color='blue', label='Processing', s=3)
    plt.scatter(x, comp_data[3][0:n_valid], marker='.', color='orange', label='Transfer', s=3)
    plt.plot(x, comp_data[4][0:n_valid], color='black', label='Total') #, marker='o') #chk
    plt.ylabel('Component Milliseconds')
    plt.xlabel('Total Milliseconds')
    title = loc + ' Past Week curl Component Data'
    plt.title(title)
    plt.legend(loc='best')
    plt.show()

The plot consists of different colored dots for each curl performance component, plotted versus the total time for the call. The plt.plot() code adds a black line that plots the total call time as a reference: the summed time of the four different colored dots at a specific x value is equal to the equivalent point on the black line directly above the column of dots.

The scatter plot for the week’s World Bank Countries API calls from Oregon looks like this:

The legend tells us which curl component each color of dot represents.

From the plot we see that the yellow and green dots lie within a small y range. This means that, over the course of the week, curl Transfer Time and Connect Time varied little. Since these performance times were nearly constant, the conclusion is that total performance times for calls from Oregon were not significantly impacted by Transfer and Connect time.

The blue dots indicate that Processing Time, while for the most part consistent, sometimes had substantially high outliers.

The red dots form a different pattern. Rather than clustering around a narrow y band, they run mostly parallel to the black line that represents total call time. This means that, for most calls to the API, the total call time is determined mostly by Resolve Time. However, in some cases the total duration of the call was most impacted by unusually high Performance Times (see the dot columns where the blue dot is the highest).

In my next post, I’ll compare the Oregon performance scatter plot with the equivalent plots for calls from Ireland, Japan, and Washington, DC.

–Kevin Farnham