Hacker News new | ask | show | jobs
by WJW 2097 days ago
The lack of compile time in the ruby world really makes it difficult to do a lot of work there. :P

There's a nice Ruby trick btw where you put significant precalculations in constants, since the value of a constant gets computed during program startup it still allow you to do work "up front" instead of during a web request.

1 comments

I never knew that but that IS a cool trick.
I just want to caveat this as it is not a Ruby construct, it's part of Ruby web servers. Because they are long-living Ruby processes they are only loading files once (I suppose it's similar to compiling). This means it runs all globally-scoped code, which class definitions and constants (generally) are. That's actually what Ruby bootloaders like Spring and Zeus are doing on your dev machine to speed up the load time when you use Rails commands. They cache all that globally run stuff in their own process. It's also why they run into a bunch of issues when you have logic in your constant definitions.
Yep, that's a good trick. At a previous PHP shop we had a large amount of static XML configuration (well it was generated, but not that often). Converting it all to PHP arrays and including it was significantly faster than parsing the XML on each request, and then PHP would cache that result too. Re-running the XML->PHP tool just caused it to re-include/cache these giant arrays of static config. It worked great. I mean, arguments about whether that was a good design or not aside...

(edit to reply since I can't reply to a reply to a reply)

Yep, it is very common in lisp/smalltalk environments to dump the state of the world to disk and re-load it later. This is one of those tricks that gets relearned every generation. :)

For bonus credit apply this analogy to docker images. :)

I did this in PHP once as well. I had to code a coupon lookup site where people entered coupon codes and they were verified against a database. I forget how many coupons there were... pretty sure it was less than 100,000.

Anyway, I coded it up in my local dev environment. Unfortunately, it turned out that I'd been mislead and the actual deployment environment didn't have a database server available.

In desperation and facing a deadline, I dumped all the lookup values into an array in a PHP file. As you said, it was really quite performant. The first request after starting the server was a bit slow (but not too bad... still < 10 seconds I think) and after that things were golden.

I felt a bit dirty, but things worked and we got paid.

I heard emacs did that but went one step further, they dump the memory of the interpreter post-init* and just load it into memory when starting.

* Some early step in the init process. Many things are still interpreted at init.

"emacs unexec" is the search term if you're looking for it.

https://news.ycombinator.com/item?id=21394916

https://lwn.net/Articles/707615/ "The Emacs dumper dispute"

https://lwn.net/Articles/673724/ "Removing support for Emacs unexec from Glibc"

I heard emacs did that but went one step further, they dump the memory of the interpreter post-init* and just load it into memory when starting.

* Some early step in the init process. May things are still interpreted at init.

What? Don't global variables exist in pretty much every language on the planet? This isn't a "trick", it is a bad practice which should be avoided in any language.

Imagine describing globals in C, Python, or JavaScript, or static fields in Java or C# as a "neat trick"...

In Ruby, the class definition is code as well.
Where they are not code? I think you meant that Ruby class is defined at runtime with sequential imperative or functional code. Ha! You can build class from Ruby code in a string too. A lot of choice.