Here are my notes from Alex Gaynor's talk in RuPy 2013 about building an implementation of Ruby in (R)Python.
- Why? 1.5-2 years ago, a friend was building a PHP interpreter in Python. Looked fun. Realized never wrote an interpreter from scratch. Ruby is a popular language. Also, to annoy people, because some people get mad about things like this.
- "Ruby is Slow" - not a precise statement. It's a programming language, not a program. People mean CRuby. Tends to be slow at executing CPU bound tasks, for programs people commonly write. People want Rails to be faster.
- Responses: "Our app is IO bound" - not usually the case. "We make it up with programmer productivity" - true, but not a statement about Ruby. "If we need to, we'll rewrite it in X" - makes one sad.
- Why is CRuby slow? Slower than some other programming languages?
- THE COMPILER DOESN'T KNOW THE TYPES THEREFORE IT IS SLOW -> All function calls are indirect. A lot of time wasted looking up methods. All containers are of "Object", no such things as the C float array. Instance variable lookups aren't fixed.
- Let's design a fast Ruby.
- RPython, a programming language with static typing, inference, GC, syntax is the same as Python. A terrible programming language. Inconvenient, slow to compile, bad error messages. But comes with a JIT compiler generator. Any interpreter written in it can be turn into a JIT compiler. Also has useful primitives.
- Tracing JITs, like TraceMonkey in Firefox, LuaJIT. Idea is that most of the time code runs similarly across runs. JIT observes what's run, what's hot. Observes what the hot code does, generates (hopefully) much quicker assembler for that code.
- Dynamic languages are all about "maybe". Java classes always have the same field. Not so here.
- Naive method lookup using a dictionary in the class: Always takes a few nanoseconds, which doesn't sound like much but can be.
- RPython does interesting optimizations on this:
- Annotate with
@jit.elidablereplaces a method call with its result. Doesn't work if you monkey patch because change isn't applied.
jit.promote(x)will use a known value but guard it for changes. Should always be the same.
- "Quasi-immutable fields",
_imutable_fields = ["field?"]- almost never changes. Does not emit code.
- Any dynamic language semantic can be implemented with these three tricks, because they compose well.
- Naive method lookup promotes the class and method name in the dispatch function.
- By including a version in the class, which a monkey patch increments, allows optimization if the version is part of the cache key.
Current status: Very fast, incomplete, can't run much real Ruby code.
Benchmarking using performance tests from the Rubinius suite.
RPython advantage over JVM: Designed for dynamic languages. So far results are faster than for JRuby. JVM's recent invokedynamic helps them. There's also new experimental stuff.
Know Your AngularJS Inside Out
Build Your Own AngularJS helps you understand everything there is to understand about AngularJS (1.x). By creating your very own implementation of AngularJS piece by piece, you gain deep insight into what makes this framework tick. Say goodbye to fixing problems by trial and error and hello to reasoning your way through them