Skip to main content

Escape Analysis is an optimization technique whereby a compiler identifies whether a variable, created inside a function, escapes the scope of that function. If the analysis confirms that the variable doesn't escape, then it can be more efficiently allocated on the stack rather than the heap.

For example:

def build_obj
obj = Obj.new()
return obj # variable escapes this function
end

In above snippet, the variable obj escapes the scope of build_obj function since it is returned by the function. So, the obj, quite possibly, is used or can be used by the caller.

caution

This article uses Ruby code only to illustrate the concepts. Whether the snippets undergo JIT compilation (or not) is not the point that this article aims to address.

In another scenario:

def do_something
obj = Obj.new()
print(obj.id)
# obj does not escape
end

The obj is instantiated and then used within the function scope. Most importantly, the instantiated variable doesn't escape.

So, by keeping this technique in mind, what practical optimization can we achieve?

ORMs + Escape Analysis

ORMs abstract away the SQLs from the developers, but it can generate queries that are not always optimal for the use case.

In Active Record pattern, a simple fetch by ID query looks like:

def fetch_document(id)
return Document.find(id)
end

This, most likely, generates and executes a SELECT * query to fetch a row by id and then does some black magic underneath to map the result to the corresponding attributes in the Document object. The query executed is:

SELECT * FROM documents WHERE (documents.id = 1) LIMIT 1;

Retrieving all the fields is justifiable in case of the fetch_document since the Document object escapes the function, and we do not know how the caller will use the returned object. This approach ensures all the fields are available in case if some caller needs them.

In another scenario:

def send_docment(id)
document = Document.find(id)
return post(document.id)
end

The send_document still executes the same broad query as above and then utilizes only the id field from the result. However, in this case, the document doesn't escape the function, which makes it possible for us to fine-tune the query without breaking its callers. So, a more optimal approach would be:

def send_document(id)
document = Document.select(:id).find(id)
return post(document.id)
end

This utilizes a SELECT documents.id FROM documents WHERE documents.id=1 LIMIT 1 query, specifically fetching only the required id field. This is an optimal query for the send_document use case.

Why SELECT * when SELECT x do trick. - Kevin Malone, probably

Where else?

  • GraphQL queries
  • Functions in strongly typed language where the function's contract is already constrained
    export function getPostById(id: number): { title: string, body: string } {
    - const post = client.query(`SELECT * FROM posts p WHERE p.id = ${id} LIMIT 1`)
    - return { title: post.title, body: post.body };
    + const { title, body } = client.query(`SELECT p.title AS title, p.body AS body FROM posts p WHERE p.id = ${id} LIMIT 1`)
    + return { title, body }
    }

#ReadInPublic is my attempt at sharing everything that I've found insightful–with the world.

This is a collection of all the blogs/articles, that I learnt something from, organized by month and presented as a heatmap. A much easy-on-the-eyes representation of the Knowledge Graph. If you're interested on learning what this is about, here's the origin story :D.

You can even treat it as a newsletter. It gets updated with my Pocket list on 1st and 16th of every month, so do remember to visit here again.

As a long-time user of Pocket, I honor all the insightful and fascinating blogs that I come across on the internet by tagging and adding them to my Pocket list.

And every week, I go through a lot of articles on any topic that I find interesting. Today, I've accumulated over 600 700 of those, and I'm making that Pocket list available for the whole world to see–in the form of a "Knowledge Graph". So, the network graph that holds all the wonderful reads I've ever found on the internet is now live!

Go to Knowledge Graph

What's new

Thanks to the HN community, I was able to receive feedback and suggestions. And, I've managed to work on a few of them.

  • Many found the graph too difficult to traverse and preferred to see it as a list or a tree. Well, now you can! Simply clicking on the tag nodes (the larger ones) will bring you a list all the articles associated with that tag.

  • It was brought up that the data in the knowledge graph wasn't searchable through the Algolia search bar. Interesting story: the website is (well, was...) actually indexed by Algolia Crawler and the knowledge graph being the unusual page in the website, it wasn't crawl-able. So, I retired the Crawler and manually configured the Algolia index through the pipelines. And as a result, you can now use Ctrl+K or +K to search both the tags and the articles in the knowledge graph.

Answers to the FAQs

  • The color of the nodes do not represent anything. But their sizes are important though. The larger nodes are the tags, while the smaller ones are the links to the article.
  • The network graph is built using D3.js. Everything you see in the screen in /knowledge-graph path, minus the top navigation bar, is rendered using a ton of DOM manipulations and SCSS and Docusaurus's Infima.