Pat Shaughnessy, author of Ruby Under a Microscope, explains the internals of Ruby, Postgres, Python and Rust through diagrams and experiments.
HN commenters praise how he combines high-level explanation, visual aids and gritty detail, especially in his Postgres internals and garbage collection posts.
Great question.
I'm a huge fan of separating the business specifications from talking about the execution.
-------
Some runtimes will do this under the hood.
RDBMS execution plans are a good example. Plan costs are calculated using data-dependent statistics. And cache-friendliness is taken into account: in postgres, hash joins are made to fit L1 (tuples per bucket = 10) and L3 caches (work_mem default to 4MB, after which batches are introduced) [1]
Some JITs will also monitor performance and behavior, and try to speculatively prune unused paths.
But this is all letting the runtime deal with it.
-------
Execution should be treated as an orthogonal but tweakable concern. And be exposed in some way to the user.
Halide [2] is one very interesting approach, is letting user choose:
* between materialization and compute-again
* parallelism levels
* chunk sizes
* scheduling, etc.
However the storage is implied by the execution chosen. Which to me is a constraint that is automatically enforced, and not exposed.
-------
All knobs, and their consequences, should be readily available to both users and compilers.
To me, typed languages could, should contain so much more information about performance (or anything!).
The perfect abstraction should be the seamless integration of 4 languages:
* Logical business requirements (what you want done). Should be user friendly
* Business properties requirements (constraints like liveness, performance envelope, security, or…
I'm working on a little static site generator now for my own site. The PHP/SQL wordpress kind of option just annoys me and have held me back from publishing altogether (don't even get me started on publishing services and social media sites.
Well, stuff like hugo, nanoc, ikiwiki... inspirational!
My static site generator is using rake for file rules to do stuff with git hooks. It's going to depend on Ruby, but won't be a "Ruby framework". Rake might as well run php, perl, a bash script or a binary. Rake is just a wonderful tool for the job, and Ruby is about as ubiquitous as Perl these days.
Here's some inspiration: http://patshaughnessy.net/2015/1/8/using-rake-to-generate-a-blog
Be sure to check out the "power rake" talk he mentions if you haven't already.
Edit: one more thought. On the idea of teaching casual users "git", I think that's an amazing idea. It touches on tip of an iceberg: computer/scientific/technological literacy gaps. If our technologies continue down the path of "black magic," with the ever extreme dichotomy of priests who know the secrets vs. ordinary/"dumb" people who are locked out of the inner knowledge, it's just not going to be conducive to a bright future.
Remember, regular people are dependent on technology, but have begun to develop superstitions about how it works. It's magic to people!
This is such a deep issue.
It's interesting to compare this to how python does it (reference counting with generations): http://patshaughnessy.net/2013/10/30/generational-gc-in-python-and-ruby
"At first glance, Ruby and Python seem to implement garbage collection very differently. Ruby uses John McCarthy’s original mark and sweep algorithm, while Python uses reference counting. But when we look more closely, we see that Python uses bits of the mark and sweep idea to handle cyclic references, and that both Ruby and Python use generational garbage collection in similar ways. Python uses three separate generations, while Ruby 2.1 uses two.
This similarity should not be a surprise. Both languages are using computer science research that was done decades ago – before either Ruby or Python were even invented. I find it fascinating that when you look “under the hood” at different programming languages, you often find the same fundamental ideas and algorithms are used by all of them. Modern programming languages owe a great deal to the ground breaking computer science research that John McCarthy and his contemporaries did back in the 1960s and 1970s."
Beyond Go and channels, this article/post touches on a subject that is personally a real pain to me.
> It’s so cool to find yourself writing tutorial for beginners! And it's a bit painful when you are trying to implement big and sophisticated system(s). Channels are primitives. They are low-level building blocks and I highly doubt you want to work with them on daily basis.
Posts/talks that relate to beginners.
You know the drill, you only have a limited time to talk about something in a conference and you only have limited time to write a blog post. It's easy and tempting to cover the basics without diving in too much into the details.
What you are left with as a professional is very thin data on how to accomplish complex stuff.
If you look at Docker and all the talks/posts around docker, they cover the absolute basic. Where's deployment to production? where's alerting/monitoring?
One of the few people I see solve this problem is: http://patshaughnessy.net/.
I've been trying myself to do more in depth posts that cover more than just the basics, it's really hard work.
Thanks, nitrogen. Following your info led to a couple of other neat discoveries, and a bunch more useful material [1].
As a result here are some new ways I learned to get 5 from 2 + 2:
require 'fiddle'
a = 2
b = 2
Fiddle::Pointer.new(a.object_id << 1).to_value.ceil + b
=> 5
Note: This happens because calling `to_value` on the `Fiddle::Pointer` object returns a Float (2.0000000000000004) instead of Fixnum (which was a surprise to me).
And here's another using `Object#tap`:
a = 2
(a + a).tap{|x| a = x + 1}.send(:eval,'a')
=> 5
[1] These links were helpful for me. The last one is an MIT licensed book called, "Kestrels, Quirky Birds,
and Hopeless Egocentricity."
http://stackoverflow.com/questions/1872110/is-ruby-pass-by-reference-or-by-value
http://patshaughnessy.net/2014/1/9/how-big-is-a-bignum
http://stackoverflow.com/questions/2818602/in-ruby-why-does-inspect-print-out-some-kind-of-object-id-which-is-different
http://combinators.info/#kestrels
Edit: line formatting
Pat Shaughnessy's Ruby Under a Microscope[1] is a fantastic resource for looking at Ruby's internals, especially concerning parsing, Ruby's class structure, and the YARV virtual machine.
It's probably easiest to begin with a Lisp dialect, since a basic one needs only two data types (singly-linked lists and symbols) and its eval function is so simple. Peter Norvig has a great tutorial[2] on implementing a Lisp in Python.
Beyond that, it can be helpful to look at the source code for other languages similar to what you're looking to create, to get a sense of how they do things.
That's more or less what I found helpful, in any case. Good luck!
[1] http://patshaughnessy.net/ruby-under-a-microscope
[2] http://norvig.com/lispy.html