Yesterday things started improving and today I'm fully recovered...
Since Thursday I’ve been in a bit of a slump. This is a natural stage in every non-trivial project. It still hits hard, this is where most people break when it’s an open source project. It stops being “fun”. It’s important to persist though. Once we get a hello world working the energy comes back and it’s a new day!
With that I merged two PRs. This monster PR finally implements all the debugging logic so we can collect all the data we need. Then I merged a small fix which gave the performance boost I’ll discuss shortly.
Up until yesterday I still had some doubts related to my ability to deliver on my chosen architecture. Would performance be reasonable enough?
I wanted to share my suspicions about performance yesterday but chose not to do that. I’ve been in so many cases where people talked on and on… They were sure the performance problem was due to X. Then they ended up with egg on their face.
I was actually right in my “guess”. I measured the application runtime without any of the state saving code. Which means we’re just launching it with JDI and nothing else. Performance was almost as bad, that means most of my code performed fine.
So what caused the slow performance?
During development I had to remove a call to:
Actually, there were many calls. I tried a lot of things such as exclusion filters etc.
The reason I had to remove those is that they didn’t work!
The addClassFilter API should really be named
setClassFilter. Adding additional filters disables the functionality. Unfortunately, there’s no mention of this in the JavaDoc anywhere. The workaround I chose is actually pretty simple, I create multiple instances of
MethodEntryRequest and bind each to a different filter type.
Right now it’s limited to the user classes filter and the
javax packages. For the proof of concept I might add more. Naturally we’ll need more configuration options for this.
Adding a simple filter made all the difference. It reduced the networking overhead of the VM and allowed fast performance. Maybe if I had taken the agent approach (which is “in process”) I would have had better performance. Might need to re-evaluate that moving forward.
With this tiny tweak performance is now acceptable for this stage in the project life so we can move on.
I squashed and merged so a lot of my changes during this process vanished in the log. Unless you go to the explicit PR and review the commits, you won’t see that. I wrote a lot of code that ended up on the cutting room floor when I decided to pivot to using method entry/exit.
This is one of the hardest things developers need to deal with for projects of this type: the fallacy of sunk cost. I already wrote the code, I can’t pivot.
Naturally, this has value. I’m not advocating a yoyo development strategy. But we need to be ready to discard work and be objective.
A couple of people pointed out to me in private that I write code without comments.
I used to comment a whole lot… In fact my code had more comment lines than source code by a healthy margin. As you can see from my blogging, I like writing and can be pretty prolific with a keyboard. The blocker isn’t time or even effort.
The problem is that comments grow stale and most people don’t read them if you overdo them. I try to make the code simple. If it needs commenting I try to simplify further. By avoiding comments as much as possible, I make sure that people read the comments that really matter.
There’s one major exception which is JavaDoc when building a public API. That’s essential and should always be fully written. But comments in source code are often ignored.
I’ve been chasing my coverage tale for a while now trying to get the coverage to 80% with every PR. This has been pretty painful. Unfortunately the tests have a lot of code duplication and just plain hacks.
I need to do a complete overhaul of this thing but I want to get the product out first. I might not have a choice since I spent hours last night trying to get coverage past the 80% mark.
This drove me crazy the other day. Unit tests passed perfectly locally but failed to work when running in github actions. The error message indicated something weird about the spring framework packaging. Something that didn’t make sense at all.
I tried isolating environmental differences and whatnot. Turns out this one tiny line, making sure the java bin directory is in the path. This one tiny change made the tests pass. I have no idea how I guessed it. I just tried everything until it worked.
There are two directions I can take:
- Try to get the code running with Spring Boot
- Finish the CLI and generate a test for the hello world test case
I’m going with the latter and so should you whenever you run into a point like that in your new project.
When creating the project we need to build it breadth first, not depth first. We need at least a basic implementation of everything working in tandem so we can understand the moving pieces. So we can accept help in the project by third parties. Breadth helps with perspective, it “proves” the project. Depth comes later.
With that in mind I turned my focus on the CLI and implemented all the current functionality that’s still pending there. With that I have one last task to complete the proof of concept…
I want to set my sights very low for the first test. But it must mock a call for this to be a “good” valid test. This will be my main focus for today.
If I can get this to work my next priority will be getting this to run on the Spring Boot pet clinic demo. I think there will be some challenges there with filtering the spring proxies. Maybe other problems. But if I can get both tasks through this week then I’ll consider it a huge success.
Right now I’m setting up the first Freemarker generated test template, once that works I plan to wire it up with Spring MVC to create a simple code generator. Then this should be bound to the CLI. It should be relatively simple, famous last words…
I hope tomorrow we’ll have proper source code generation working with Freemarker. I’m Working on integrating it and then I’ll go over the code to generate the tests. Then this should bind to the CLI. It’s getting close!
If you want to keep up with the latest updates on this series and the many other things I work on then follow me on twitter.