Hacker News new | past | comments | ask | show | jobs | submit login

The actual memory usage is coming from the number of instantiated methods. If you write a method, it gets an entirely new implementation of it copied and compiled for every different list of argument types. For example,

    def foo(bar)
      bar + bar
    end
    
    bar1 : Int32
    foo(bar1)
    
    bar2 : String
    foo(bar1)
    
    bar2 : Int32 | String
    foo(bar1)
The above code gives you three methods to generate code for: foo(Int32), foo(String), foo(Int32 | String).

This isn't really a problem for small projects, but with large projects (60k+ loc), you end up with some methods such as puts, Array(T)#<<, etc with thousands of instantiations.

We have some edge-case semantics (we don't cast arguments to their restriction types, which we plan to remove before 1.0) which also prevent us from allowing only instantiating foo(Int32 | String) when we change the definition to `def foo(bar : Int32 | String)`. Hopefully in the future, we can allow the compiler to take advantage of method argument type restrictions to reduce the number of instantiated methods and speed up the compiler.

That doesn't mean the compiler will be super slow if you don't annotate your methods, it just means that the stdlib and shards' public API will start annotating it's method arguments more (which gives you better docs and error messages anyway).

For more info: https://github.com/crystal-lang/crystal/issues/4864




They also have a very detailed blog post about how their compiler works: https://crystal-lang.org/2015/03/04/internals.html




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: