Profiling mysteries
In our profiling, we run into an expensive mystery call to string.Join. Nothing in our code called it, and it is expensive.
Looking at the code didn’t get us anywhere, so I profiled things again, this time using the debug configuration. The nice thing about the debug configuration is that it doesn’t inline methods (among other things), so what gets executed is much closer to the actual code.
Here are the results:
And now it is clear what is going on.
Here is the offending line:
var tryMatch = _trie.TryMatch(method, context.Request.Path);
With context.Request.Path being a PathString, and TryMatch accepting a string, we are silently calling the implicit string operator, which just calls PathString.ToString(), which just calls ToUriComponent(), which looks like:
public string ToUriComponent() { if (HasValue) { if (RequiresEscaping(_value)) { // TODO: Measure the cost of this escaping and consider optimizing. return String.Join("/", _value.Split('/').Select(EscapeDataString)); } return _value; } return String.Empty; }
Looking into the current code, it has already been optimized by removing the Linq call and its associated costs, but that is still expensive call to make.
The fix was to get the string directly:
var tryMatch = _trie.TryMatch(method, context.Request.Path.Value);
And here are 10% reduction in costs.
Comments
That seems to be a good argument against implicit conversions. Are there still benefits that make having an implicit conversion a good idea?
Karg, Yes, because it improves the API for the 95% cases. And you only hit it when you are in deep profiling mode for finding all sort of hotspots
".Value" is an unnecessary verbose semantics, to be honest. It clutters code and impairs readability, confusing the reader. If you have to optimize by adding that, then there is something wrong with either the runtime that is unable to work with the string object as it were, or with the compiler where optimization would produce inferior runtime. In actuality, "value" usually means a lower level operation. A value of a string is.. a string.
John, PathString is something that abstract a path, in particular, the implicit conversion does url encoding that can be expensive. That is why you want to defer that as much as possible, or avoid it if you can entirely.
Comment preview