Performance Optimization - What not to Optimize
No, this is not a well thought-out blog post about software performance optimization and pitfalls that come with it. Rather this is an anecdote. So take it with a pinch of salt, for words and stories can be meaningless if taken out of context.
The other day I was talking to one of my friends and he wanted to run a problem by me that he was trying to solve. It was a problem about performance optimization. Well, duh, what else would it be about? It says “Performance Optimization” right in the title of this post.
He was working with a database system that exposes an API for bulk operations. For example, you could create, delete and update some items with a single request:
{ "create": { "name": "Mr. Nobody", "age": 42 } }
{ "update": { "id": 17, "name": "John Doe" } }
{ "delete": { "id": 27 } }
And he had a large array where each item represents one of these operations. Something like this:
{ "_operation": "create", "name": "Mr. Nobody", "age": 42 }
He said he was struggling to prepare the body for this request. And the table was turned. Now, it was me who was struggling to find the struggle-worthy problem in there. Because regardless of the language being used, the solution would look somewhat like this:
const operations = []for (const item of items) {
const operation_name = item._operation
delete item._operation const operation = {}
operation[operation_name] = item operations.push(operation)
}const requestBody = operations.join('\n')
Before you say something, yes, I know that even a thing so simple as this can feel daunting to somebody who’s just starting to learn programming. But that’s not the case here. I promise you this is about “Performance Optimization” as it says in the title.
So I told him exactly what I was thinking, “Have you tried looping over the items and create a string representing the desired shape for the request body?”
He said, “Yeah, that works. But I’m trying to optimize it. There are thousands of items and looping over them is not very perfomant.”
That got me even more confused, so I asked, “You’re trying to optimize out the ‘for loop’?! You said it’s not very perfomant, compared to what?”
To which he said, “If I have to loop over each item separately, what would even be the point of using the bulk operation API anymore? I might as well call individual API for each item.”
Wait, hold up! That doesn’t add up! Does it? 🤔
The cost of a network call can’t be comparable to the cost of a single iteration of ‘for loop’ here. A single network call doing bulk operations is definitely gonna be more performant than doing a thousand network calls for those individual operations. Yeah, it definitely doesn’t make sense. And as I explained it to him, he understood it completely and agreed with it.
Knowing what not to optimize is important. And how you know that is by measuring it. If you don’t know difference between the time it takes to make a network call and going through a loop iteration, you’re bound to make silly mistakes.
So before thinking about optimizing stuffs, ask yourself, do you really need to do it? Are you really focusing on the right thing?
And that, my friend, is a reminder for myself and for any of you who sometimes feels tempted to optimize stuffs where it’s not needed. There’s no point in denying it, we’ve all been there and we know it. 😂
Originally published at muniftanjim.dev on September 25, 2021.