Sunday, January 4, 2015

Explorations in Node: A simple symbol server proxy

Being a native code developer and working on one a project as large as Windows and Internet Explorer I find that I spend a lot of my time in the debugger working with symbols. Generally the debugger is really good about fetching only the symbols it needs and limiting its queries, but other times it fails miserably and really wants that ntdll pdb.

My core job is also as a performance developer. Which means in addition to debugging I'm also processing a lot of ETW traces or ETLs using a tool called WPA or Windows Performance Analyzer. For various reasons it turns out that symbol loading in this tool, especially when working with monolithic binaries and private symbols, can take quite some time. And we aren't the only ones to have the problem as it appears even Chrome has monolithic binaries and symbols per a series of posts from a former colleague, Bruce Dawson.

I could claim that this impacts me greatly, but it doesn't impact me nearly as much as it does my boss who started the original project to fix the problem. You can see Rico's solution over on his blog. He wrote his solution in C# using the built in networking facilities of the .NET Framework. Even with a solution partially in hand, there is opportunity to learn from this experience, so let's begin.

Interrogating the Problem Space

When Rico first talked to me about this problem he was in the middle of defeating the many dragons in the .NET Frameworks networking stack in order to get the experience that he wanted. He was already a few hours in and was "almost done" so changing directions, for him, at this point would have been a waste of time. Instead of resetting we just walked through the problem space and asked if there were any more immediate solutions. I proposed, Eric Lawrence's Fiddler since I had written numerous filters in that tool before and it is "pretty easy" to do but probably not as easy to package.

My next thought was, isn't Node.js designed for this whole request interception problem? Its also very good at setting up lightweight servers which meant it might be good for sharing the solution with the entire team (if someone ran the server, then not everyone would have to run their own proxy). After interrogating the problem space it was pretty obvious that Rico's solution had a lot of value and it would also be expensive to explore the other options. It looks like we had a winner, but I still wanted to use this as an opportunity to learn more Node.js.

Implementing the Solution

It turns out that a proxy connection is basically a starter tutorial for using Node.js so when I sat down in the evening to give it a try 80% of the code I needed was sitting out there on at least 30 different blogs. I read through a few and then hacked away on a simple proxy. My overall contribution was just enough code to configure the server with some basic variables like where the remote symbol server should be and symbols you want to be downloaded. After a bit of testing, I was able to verify that launching WPA and I was able to filter down to just the symbols I cared about and that under the debugger I was able to remove lengthy delays as well. An overall success!!

Reflections on Learning

Something that I thought would take me many hours was actually complete in about 15 minutes. This really showcased the power of Node.js, but it also showcased something else about learning. Previously I noted that unless taking the time to learn was going to clearly cause you to fail or miss a deadline you should try to favor something new over applying things you are already intimately familiar with. You really need to find the fun and opportunity to grow in your solution. For me, this reintroduced me to Node.js after having shelved it for quite some time. Feel free to take my final code, learn from it and compare it to Rico's solution as well.


No comments:

Post a Comment