Skip to content

Comment on Never create Ruby strings longer than 23 characters

Comments

I have this sinking feeling reading that article took more time than I'll ever save by knowing this.

Computers go unimaginably fast now. Really. Humans can't intuitively comprehend how fast it is. I doubt that this fact will save perceptible time for more than a dozen of its readers.

Okay, knowledge of this specific optimisation wouldn't be that useful except in some very unlikely scenarios. Nevertheless, I found this to be an interesting read about some Ruby MRI internals.

But I have to disagree with your attitude toward optimisations. Algorithmic improvements (and implementation optimisations, but generally less so) can improve performance by many orders of magnitude. Sure, sometimes it just doesn't matter, but there are plenty of cases when you should pay attention to this. For example: any web service that runs on more than a couple of servers. At some point, it will be cheaper to spend more time writing efficient software than to add hardware. Another example: mobile devices. Can you make your software 20% faster? Great, that means 20% more battery life.

I have a recent example which left a strong impression on myself. I have implemented a bot which plays Kalah[1] for a school project. I've used C and I've optimised the program as much as reasonable in a week or so. After I was done, I've looked on the web for a strong implementation to play against. I've found a bot implemented in Ruby. To my surprise, my implementation was about 4 orders of magnitude faster. A friend implemented the same thing (including algorithmic optimisations) in Java. Guess what, his was still 2 orders of magnitude slower than mine.

TLDR: Yeah, most of the time computers are fast enough. But if you have hotspots, it often pays off to optimise that code.

[1] http://en.wikipedia.org/wiki/Kalah

>I have to disagree with your attitude toward optimisations

How can you, you don't know it?

This is a tiny little fact about string runtime speed in something that is not the tight loop of the program in question running.

Optimizing on this basis is called a premature optimization. You've not pointed a profiler at the code, you don't know a significant portion of the runtime is in this string creation function, so you make larger, more complicated code that getting around this implementation detail of the current ruby interpreter.

Do you know if you made your program faster or slower by doing this change? No, you don't. You have to add this optimization at the end, if and only if you see that this routine is taking a bunch of time. Why?

Adding this extra code can make your program not fit in your processor cache, HUGE SLOWDOWN. Adding this extra code may make extra non-trivial work to work with data that dwarfs the small time saved by thousands (it wouldn't take much to do that). Adding this extra code can make your program require extensive weeks of rewrite and testing, costing thousands more dollars that could instead be spent on better hardware. Adding extra code to work around this could cause optimization in a compiler or library to not kick in, slowing your code.

When optimizing, you should be hand optimizing only the hotspots, not the rest. This article is talking about something that has almost no chance of being the hot spot, and acts like it's essential to never do it. Hence, it is untrustworthy, as the author did not know enough to know how unimportant this fact is to most people, or is dishonest enough to not express that to his audience while knowing it himself.

>> I have to disagree with your attitude toward optimisations > How can you, you don't know it?

This bit

> Computers go unimaginably fast now. Really. Humans can't intuitively comprehend how fast it is.

seems to imply that you think computers are so fast that performance shouldn't be more than an afterthought.

I'll repeat myself: I don't think anyone should explicitly try to exploit this implementation detail. It's just that you seemed to dismiss all performance considerations.

> When optimizing, you should be hand optimizing only the hotspots, not the rest. This article is talking about something that has almost no chance of being the hot spot, and acts like it's essential to never do it.

No, it doesn't. The first paragraph starts with "Obviously this is an utterly preposterous statement: it’s hard to think of a more ridiculous and esoteric coding requirement."

Maybe it's not entirely rational, but I'm not a fan of this attitude even disregarding the points about scaling and mobile devices in the sibling post.

Computers are unimaginably fast, but people still wince at software that feels unresponsive or has long startup times. Dynamic, interpreted languages like Ruby are still considered prohibitively slow and not (or rarely) used for system programming, fancy 3d engines or embedded programming. Some people allegedly still write web browsers in C++!

If dynamic languages want to grow their (unquestionably already significant) niche, they can't wait for hardware improvements to make the order-of-magnitude difference to C not matter, and they can't afford to pass up optimization opportunities (that their bare-metal competition is probably taking as well).

Now you can write that off as an implementation detail and ignore whether it buys you perceptible time savings or not, but I don't feel it's right to handwave away all optimisation considerations. The article is an interesting little insight in how things are done in the engine room and what kind of shenanigans are employed to ultimately make your RoR web app load a teensy bit faster, and I don't consider the time I spent reading it (and subsequently having a look at the surrounding areas in the code) wasted at all.

The fact this is only a 50% time increase is why casting the piece as an important optimization is frankly making the piece illegitimate.

If it took 10x or 100x the time, then you have something to talk about. 1.5x? Not Worth Mentioning. Definitely crappy hyperbole that linkbaited a bunch of people to waste their time reading it.

If you're worrying about 1.5x speedups in non-tight loop parts C++ code, I would contend you're probably looking in the wrong place. Even in a tight loop, 33% faster isn't much to write home about.

The thing about all this is: It doesn't make your web app load a "teensy bit faster". The time required to make millions of strings like this is still far far far below that of human detection.

I'd contend, if it made the memory footprint of the program any larger (with larger code pages), accommodating this could Very well slow your startup time down if it made the code page a bit bigger cause a processor cache miss to load another module you had to write to handle using artificially small strings.

This isn't handwaving at the issue of dynamic language runtime speed. That's a strawman of your own construction. This is me pissed off at such a dramafilled title being slapped on an inconsequentially small speed difference in Ruby strings.

I've been similarly pissed off in meetings where people spent 2 hours arguing for an "optimization" that would have saved a total of ~400 ms total if we sold 100 million units and they ran for an average of 20 years each.

This isn't about scaling. This isn't about optimization. This isn't about making dynamic languages faster. This is about saving functionally no time, ever, and usually wasting people's time and making the code slower with premature optimization.

Did you read the article? The very first sentence is

"Obviously this is an utterly preposterous statement: it’s hard to think of a more ridiculous and esoteric coding requirement."

Or how about this:

"Don’t worry! I don’t think you should refactor all your code to be sure you have strings of length 23 or less. That would obviously be ridiculous. The speed increase sounds impressive, but actually the time differences I measured were insignificant until I allocated 100,000s or millions of strings – how many Ruby applications will need to create this many string values? And even if you do need to create many string objects, the pain and confusion caused by using only short strings would overwhelm any performance benefit you might get.

For me I really think understanding something about how the Ruby interpreter works is just fun! I enjoyed taking a look through a microscope at these sorts of tiny details. I do also suspect having some understanding of how Matz and his colleagues actually implemented the language will eventually help me to use Ruby in a wiser and more knowledgeable way. We’ll have to see… stay tuned for some more posts about Ruby internals!"

I truly do not understand the emotional reaction you were having when you wrote this comment. It sounds like you've had some issues in the past with your time being wasted debating pointless optimizations, and that's what you were reacting to.

The article is not advocating pointless optimizations. The article is simply exploring a cool little piece of MRI.

It sounds like you have a lot of experience with dealing with optimization, though. It'd be cool if you wrote something educational about optimization.

Except in the most egregious cases, how many optimization articles ever save you more time than it takes you to read them? As you say, computers are unimaginably fast.

Indeed. I am just continually amazed at the lack of caution people make when expressing these sentiments

"Never use a ruby string longer than 23 characters!!!"....or you'll just take a slightly less infinitesimal amount of time.

I think the title is meant to be a hook.

so premature optimization in code is evil for more than one reason. First, it obfuscates the code. Second, the slowest processor around is the wetware, and it aint getting any faster. Making it simpler to understand/explain/write/compile/debug will save geometrically more time than it saves in almost every case.

AboutSource Built by g1lg1l

Hackerly is an independent reader for Hacker News, built on the public HN API. Not affiliated with Y Combinator.