RC W6D3 - Finding a success metric

Compilers

In yesterday's post, I described taking a closer look at how a browser works (in particular, HTML/CSS rendering) as well as compilers, but left out discussing the missing piece connecting the two - executing JavaScript.

We can think about JavaScript execution as translating source code to machine code (which the computer understands). This step could be done through the use of an interpreter, which translates and executes line-by-line. This allows for a fast startup time, but can be slower overall since the same translation may be done over and over again. The other option is to use a compiler, which translates all the source code at once prior to execution. This allows for more optimizations but is more complex and thus slower to start.

Modern JavaScript engines like Chrome's V8 combines the 'best of both worlds'. It starts by running the source code through the interpreter, but also has a profiler that identifies parts of the code that are run repeatedly. These are then recompiled into highly-optimized machine code, allowing for impressive speed ups over time. This process is known as just-in-time (JIT) compilation.

When running microbenchmarks, I was surprised (and impressed!) to find JavaScript performance times to be comparable to Rust. What I didn't compare was memory usage, though perhaps you're already familiar with this from using Chrome. Writing high performance JavaScript is very much tied to keeping the JIT happy, which got me looking at compilers.

A discussion of how V8 makes trade-offs - running a single line of code vs iterating through a loop, memory usage in laptops vs mobile - can be found in the Google I/O talk here.

Startups

Andrey and I talked about startups over a fun coffee chat today. We have a tendency as developers to build something cool that we think will translate well into a startup, but in doing so overlook two key skills.

The first is the skill of 'making money'. This involves being mindful about the commercial aspects of the product (potential user base, how to monetize, pricing) as well as the business in general (accounting, payroll, AWS bill). Naturally the idea here is to have money in exceed money out, or at least, be able to pitch VCs that you'll end up in this state.

The second is sales. While it's easy to think of sales as a part of the first skill, it's clearer as a separate skill when you think about how you can sell something that's free. Sales more broadly involves growing the adoption of your product; a large user base helps create a large paying user base.

A useful analogy is to think about being a good developer and being good at interviews. The two skills reinforce each other but involve different training regimes. Keeping the two distinct helps us break down real-life examples into 'case studies' and assess how well they do in each dimension.

What's very interesting is how Andrey uses this framing for open source software - he leans towards building something that's cool but also something easy to explain and easy to demo.

Content: Sam Altman

I enjoyed the New Yorker profile of Sam Altman so much, I still keep the physical copy. I know, I should have kept the one on Jack Dorsey too.


The article has a brief history of YC and how it's changed under Altman, including this great excerpt.
Launching a startup in 2016 is akin to assembling an alt-rock band in 1996 or protesting the Vietnam War in 1971 - an act of youthful rebellion gone conformist. Since 2005, the year Y Combinator began, accelerators have sprung up everywhere to help transform startups from a skein of code into a bona-fide company.
Altman has since moved to leading OpenAI. He's true to form on gambling on the next moonshot, as per the advice from his post. The question for myself is, what's my success metric?
It’s useful to focus on adding another zero to whatever you define as your success metric - money, status, impact on the world, or whatever. I am willing to take as much time as needed between projects to find my next thing. But I always want it to be a project that, if successful, will make the rest of my career look like a footnote.

RC W6D1 - Grow the puzzle around you

Python

I've been a little distracted today, moving between browsers, V8 and JIT. Given the success of JIT, I'm a little surprised it's not more widely adopted by other languages, or perhaps, I just haven't noticed it before.

I also switched back to Python after time spent learning Go and Rust, in light of algorithm interview prep in the coming weeks. It took me a bit of time to adjust, but it felt liberating once I got started. It's like speaking a language without having to search for the words, allowing you to focus on the conversation itself.

Content: Grow the puzzle around you

I know I'm not in the Bay Area anymore when I have to explain what Y Combinator is. YC is a three-month startup school where founders receive coaching on how to refine their product and sell their ideas to investors. Its head-turning record of success has inspired hundreds of other accelerators worldwide, keen to replicate YC's investment and training philosophy (source: The Economist).

I admire how YC has an emphasis on nice people. Founders are assessed as to "whether they're good people or not", consciously avoiding "jerks but who seemed likely to succeed". YC open sources a lot of its material, for example the Startup School online course, and promotes founder-friendly investment terms.

It's been noted how the close-knit feeling might be diluted as the program grows; the 116 startups per batch in 2015 is now 197. What we can perhaps agree on is the wonderful content made available. I'll share my favorites over the next few days, the following by Jessica Livingston.

You are a jigsaw puzzle piece of a certain shape. You could change your shape to fit an existing hole in the world. That was the traditional plan. But there’s another way that can often be better for you and for the world: to grow a new puzzle around you. That’s what I did, and I was a pretty weird-shaped piece. So if I can do it, there’s more hope for you than you probably realize.

RC W5D2 - Relentlessly resourceful

WebAssembly

I ran a demo on WebAssembly at Presentations last Friday. I had to gloss over a number of details given the 5-minute format, so I did an extended version today.

As per Lin Clark's post, WebAssembly is "taking code written in programming languages other than JavaScript and running that code in the browser". Today I added how a major project underway is a standalone runtime so .wasm binaries can be run independent of the browser.

Re: portability, I previously used the following image with C, C++ and Rust as starting points. These so-called system languages are particularly suitable for compiling to WebAssembly given the absence of a garbage collector and minimal language runtime. I'm often confused by the term runtime, more detailed explanation here.

Re: performance, I had mentioned how WebAssembly gets to skip some execution steps compared to JavaScript. The wrinkle is the JIT currently doesn't know how to deal with WebAssembly directly, limiting speed gains (see 'trampolining' here). In fact, the main example I've come across in practice is a Figma post focusing on speed ups from smaller binaries.

Re: security, I had skipped this entirely. I provided a high-level overview of the ArrayBuffer today.

In the demo, I compiled and ran WebAssembly. I spoke a bit more on future improvements on the roadmap (see 'post MVP features' here), in particular access to the DOM and direct loading of WebAssembly modules (hence no need for a web server).

Microbenchmarks

Reviewing the feedback on the 5-minute presentation, comparing the performance of WebAssembly against JavaScript was at the top of the list. What's amusing is I wanted to learn WebAssembly but ended up having newfound respect for the V8 JavaScript engine.

I started with prime number generation, and puzzled how WebAssembly ran slower against JavaScript. Then I realized how even the Rust implementation ran slower against JavaScript. Andrey found a post on this exact comparison. My sense was the execution involved one main loop, which provided a textbook example for JIT optimization.

Moving on, I found a post on Julia microbenchmarks and thought I can simply use the tests where JavaScript wasn't as fast. Running matrix multiply, I had LLVM issues and discovered I needed to install Fortran to use BLAS. Oh boy. Post-installation I might still have been missing some symlinks, so kept this on hold for the time being.

With quicksort, Rust completed in half the time of JavaScript but I didn't have time to set this up in the browser before the presentation. I did have the n-queens problem as an example where Rust (compiled to WebAssembly) ran in half the time of JavaScript, in the browser.

When running microbenchmarks in the past, it's always been about comparing two algorithms in the same language. Cross-language benchmarks are fascinating. Do you replicate step-by-step, or rewrite in the way the language performs best (hence needing to know best practices in both languages)? If the latter, would there be more subtlety when comparing imperative against functional languages?

The other issue I had was microbenchmarking in the browser. If you set up the start and end times in JavaScript, does this mean you can't time the parsing stage (since by that point the code is already parsed)?

Content: 15 startups in 21 months

In his essay, Paul Graham isolated the key quality needed in a founder - relentless resourceful(ness). The story that often gets told is of Airbnb, where the co-founders managed to extend their runway by selling cereal during the 2008 Presidential Elections. The story I quite like is actually this one.

https://medium.com/@mecolalu/how-we-did-15-startups-in-21-months-a7008c8f2c97

There's a happy ending; I won't spoil it more than that.

RC W4D1 - Maximize your learning

On exposure

Every Friday I would look back at the past week, but would be too wiped out to articulate it clearly. This occurrence was especially annoying last week, as it marked a quarter into the batch.

I've covered a number of different areas in the first three weeks. At a coffee chat today I realized the time so far had not reinforced my interest in any particularly, but instead exposed me to a whole new world of things. Suppose I had three choices before, how strongly I feel about each of them hasn't really changed. However I now know there are seven choices.

Rust

I'm very much enjoying Rust. I haven't done it for long so I won't say too much, but it appears the compile times can take a while. That being said, a toy implementation of generating the 10,000th prime number averages at 0.25 seconds for Rust vs 3.88 seconds for Python (code here, inspired by post here).

Over the weekend I discovered RustPython, a Python interpreter in Rust. Since Rust can be compiled to WebAssembly, the interpreter can be made to run in the browser. The FOSDEM 2019 talk can be found here.

Content: Learning at startups

I've always believed in choosing a role that allows you to maximize your learning. In the context of startups, Paul Buchheit says it best.

https://triplebyte.com/blog/interview-with-gmail-creator-and-y-combinator-partner-paul-buchheit

I would suggest thinking about joining a startup as more like going to grad school to learn. Optimize around learning when choosing a job. That’s the best thing. Then if a startup fails, you can always go back to Google and probably get paid a lot more, because now you’re actually a much better engineer than you would have been if you had stayed there like everyone else.