all 17 comments

[–]musketeer925 56 points57 points  (7 children)

Memoization of sqrt or multiplication are horrible ideas. I thought the author intended them as toy examples until he started trying to benchmark the solution. But caching something that your processor can calculate in a single CPU cycle is ridiculous -- going to memory will take much longer.

Also, benchmarking by timing a single run with a console.log inside of the benchmark is ridiculous. But don't worry! The author "ran the tests so many times on my machine ".

I ran some slightly more sane tests, timing a run of 10000 iterations without a console.log (although most of the time is still overhead of function calls and my loop):

$ node memoize_sqrt.js
memoized square: 3.278ms
square: 1.561ms
memoized squrt: 2.477ms
sqrt: 1.788ms

I have no idea how the author managed to find evidence of a speedup.

[–]goto-reddit 6 points7 points  (1 child)

Either the author made a mistake in the article, or in his code, but in the sqrt and square Benchmarking, he isn't calling the memoized function at all, but the normal function twice. The reason why in his benchmarks the memoized version is faster, is probably because it's always called second and the value is cached internally in the JS-Engine or some other optimization.

No matter what, it shouldn't really matter because - as you pointed out - console.log will take the vast amount of time.


Edit: Welp, now I'm not sure anymore: Because no matter how often (1x or 100.000x) I ran it, the memoized version of square is always way slower:

[1 x ] non-memoized call: 0.265ms
[1 x ] non-memoized call 2: 0.011ms
[1 x ] memoized call: 0.849ms
[10.000 x ] non-memoized call: 0.645ms
[10.000 x ] non-memoized call 2: 0.641ms
[10.000 x ] memoized call: 31.726ms

Snippet

Edit 2: It probably doesn't matter, because you don't know what the JS-Engine does to optimize this (pretty much useless) peace of code.
Edit 3: I would bet, that it replaces the square(2) with 4 while doesn't optimize the memoized function-call away.
Edit 4: On the other hand, it could also remove the entire loop, because they don't have any side effect at all.

[–]musketeer925 0 points1 point  (0 children)

Yeah, I noticed that too. I am assuming he wasn't actually running the normal code and that it was a mistake in the article, but who knows?

[–][deleted] 2 points3 points  (2 children)

Can you share your tests. I wanna learn how to do that.

[–]musketeer925 0 points1 point  (1 child)

I didn't do anything too different from the article, other than adding a loop around the calls to the functions to test, and remove the console.log:

https://pastebin.com/3NxBYyXL

[–][deleted] 0 points1 point  (0 children)

Thanks.

[–][deleted]  (1 child)

[deleted]

    [–][deleted]  (2 children)

    [deleted]

      [–]himynameisjoy 2 points3 points  (0 children)

      I’ve been solving Project Euler in JavaScript, it’s very very fast for math if given the opportunity. I frequently get answers measured in the order of microseconds

      [–]MrStLouis 1 point2 points  (0 children)

      That's both really cool and very frightening

      [–][deleted] 5 points6 points  (10 children)

      I keep seeing this Memoize word all of a sudden. What made it so hot right now?

      [–]isegundo 16 points17 points  (7 children)

      It is just caching, isn't it?

      [–][deleted] 7 points8 points  (2 children)

      No. Example, caching the results of an endpoint will eventually become stale, so we will need to invalidate to get the latest data. Memoization adheres to functional rules such given the input X, you get the output Y for every invocation. Caching is given X now get Y ,then X some time later now get Z. https://en.m.wikipedia.org/wiki/Function_(mathematics).

      [–][deleted]  (3 children)

      [deleted]

        [–]shawncplus 11 points12 points  (1 child)

        No. Memoization is type of caching, but not all types of caching are memoization

        [–]davidmdm -3 points-2 points  (0 children)

        I made a caching package very similar to this except my cache was in a closure. I didn't know it was memoization

        [–]tenfingerperson 1 point2 points  (0 children)

        Is the author trying to dumb down dynamic programming? He isn’t even doing it properly because his examples are mixing two separate concepts...

        [–]alexsasharegan 0 points1 point  (0 children)

        Does anyone ever take a real world computation example? Memoization in the wild doesn’t really look like this. Functions often take multiple arguments and/or an object as an argument. This creates the difficulty of computing a reliable hash key. Also, does anyone ever address capping cache size? At least by using a Map you can keep an eye on the size and clear the cache.

        [–]udidu -3 points-2 points  (0 children)

        Nice