Code Analysis

As discussed in Traceable Layer and Tracer, the final output of a Traceable call is a large block of XML data. As we drill down into the data, we are able to see what functions are called, as well as all the values that were used. We can determine what was going on in the code, and if we need to make changes to the code. However, Traceability gives us additional benefits beyond troubleshooting.

Analyzing Work Load

Typically experienced developers looking at the algorithmic complexity of code is able to ascertain the code's asymptotic behavior, i.e. we can usually tell if a piece of code is going to run in linear time, or n-squared time. However, there are typically other factors that are not so obvious.

For example, I worked on a system that would sort and match various data elements in a large set. The specifics of the sorting and matching involved looking at 5 or 6 different facets of each element. An interesting aspect that Traceability gave us was the ability to see how much any given facets were actually used. And when we made any code changes around the facets, we could then see the impact based on the trace data.

General Efficiency

One area that is often missed is how many times common code is reused in a service call. Generally speaking we can look at a service call as having several sub-calls that perform the necessary actions before returning a result.

High Level View of a Service Call

Each sub-call may be broken into all the supporting functions necessary to complete the the requirements of the sub-call.

Service Call with Underlying Functions

And if there is code that can be used in multiple sub-calls, we move that code into shared functions. And this is where we fail.

High Level View of a Service Call

Reusing code is a very good design pattern. However, from my experience, most developers are only worrying about the functionality of the specific sub-call. They may note that a function is being used in another sub-call, and move the function to the "common" code area so that they may use it again. But they don't necessarily worry about the impact of calling the shared function from multiple places.

As an example, there was a service call that had over twenty sub-calls to collate various values. Each sub-call was designed in overall isolation from the other sub-calls, and thus could all be treated as independent calls. The problem was that several shared functions would be called from several of the sub-calls. And each time one a specific shared functions was called, it would always return the exact same value. In one particularly egregious case, one of the functions could be called thirty to forty times, and it was one of the most expensive calls in the system.

When the trace data from the service call was looked at, we immediately starting seeing the same XML blocks being repeated through out the output. This let us quickly identify what shared functions were being repeated the most. After identifying them, we then knew where we needed to add memoization to reduce the overall workload of the service call.

Request Efficiency

Another aspect that Traceability allows you to examine is how much data from a service call is actually being used. For example, we have a cloud service that calls another cloud service for some information.

Cloud Service Call

We can use Traceability in the calling service to determine what data is actually being used. Once this analysis is done, we can look into reducing or removing data that is not being used prior to the called service sending a response. This data reduction can be particularly important when dealing with cloud based services, where the amount of data being sent and received directly impacts the service charges being accrued. In a non-cloud situation, the optimization will help reduce internal network traffic.

Cloud Service Call

Next: Tool Design