4 ms·
I would advise against concluding anything with < 20% gain, the changes often impacts readability (the intention becomes less clear) and might as well be measur
by eregon 11y ago
I would advise against concluding anything with < 20% gain, the changes often impacts readability (the intention becomes less clear) and might as well be measurement errors or just be insignificant for any sort of real application.
Not to mention, of course, these measurements are specific to a given system, implementation, etc.
- flowerpot 11y agoI agree, before you start implementing all these changes you should probably also spot the time consuming parts of your software using a profiler. Otherwise you might be making a bad trade-off. My software engineering professor always used to say: "Never start optimizing before you have measured [using a profiler]."
- epidemian 11y agoAbsolutely. Moreover, many of these minor run time differences are bound to change from one Ruby version to another[1]. I would even consider it harmful to remember many of these numbers as some sort of practical knowledge. I've actually known cases where a programmer would use some extraneous idioms and when told about a more idiomatic solution it turned out that they knew there was a more idiomatic way of doing it, but they used the more obfuscated alternative because "it was more performant". But it turned out that that knowledge was obsolete (it only applied to an old VM version) or incomplete (it only applied in some very specific cases). So, beware of "knowing" that `arr.last` is slower than `arr[-1]`. It might not be for too long[2]. [1]: I'm speaking about MRI versions here; of course all those measurements are off if you use JRuby, rbx or Opal. [2]: It is useful to remember that `arr.bsearch` on sorted arrays is faster than `arr.find`. That probably won't change in the near future ;)
- JohnBooty 11y agoYes. That is sane and important advice when talking about any optimization in any language. Unless it's an execution hotspot in your code, value clarity and maintainability over performance. Most of the speedups in these optimizations are very small in absolute terms (only a few milliseconds each) so they will only provide a real-world benefit if they're being called in a loop or something. That all said: 1. A lot of these optimizations are also a win when it comes to clarity (Array#sample is faster and clearer than Array#shuffle.first) 2. Knowing that the "bang" version of a method is always destructive and nearly always faster is a good thing to remember in general for Ruby
- eropple 11y agoGenerally I agree with this thinking, but a number of the idioms in this repo (respond_to? rather than begin/rescue) do have a fairly significant perf benefit and are easier to read. And some of the other lessons, like "don't use method_missing if you can define a method instead", are well worth considering as well.
- epidemian 11y agoA minor nitpick: > And some of the other lessons, like "don't use method_missing if you can define a method instead", are well worth considering as well. I'd argue that this one also falls into the category of "simpler/more readable and, incidentally, more performant". When defining methods you get the correct behaviour of respond_to? for free, whereas when overriding method_missing, you also have to take care of defining a corresponding respond_to?. The main reason for choosing def/define_method over method_missing (when possible) should be that it is generally simpler to do so.
- eropple 11y agoDepends on which way you look at it, I think. Like, when building a DSL, I generally take my inputs and do the work up front to use define_method--but I know people who feel that it's simpler to just use method_missing and check against some bit of data here or there. The perf argument isn't going to change their minds overnight, obviously, but I think it helps to make sure you have all the information.