• Keith Randall's avatar
    cmd/compile: captureless closures are constants · 4f97ec08
    Keith Randall authored
    In particular, we can initialize globals with them at link time instead
    of generating code for them in an init() function.  Less code, less
    startup cost.
    
    But the real reason for this change is binary size.  This change reduces
    the binary size of hello world by ~4%.
    
    The culprit is fmt.ssFree, a global variable which is a sync.Pool of
    scratch scan states.  It is initalized with a captureless closure as the
    pool's New action.  That action in turn references all the scanf code.
    
    If you never call any of the fmt.Scanf* routines, ssFree is never used.
    But before this change, ssFree is still referenced by fmt's init
    function.  That keeps ssFree and all the code it references in the
    binary.  With this change, ssFree is initialized at link time.  As a
    result, fmt.init never mentions ssFree.  If you don't call fmt.Scanf*,
    ssFree is unreferenced and it and the scanf code are not included.
    
    This change is an easy fix for what is generally a much harder problem,
    the unnecessary initializing of unused globals (and retention of code
    that they reference).  Ideally we should have separate init code for
    each global and only include that code if the corresponding global is
    live.  (We'd need to make sure that the initializing code has no side
    effects, except on the global being initialized.)  That is a much harder
    change.
    
    Update #6853
    
    Change-Id: I19d1e33992287882c83efea6ce113b7cfc504b67
    Reviewed-on: https://go-review.googlesource.com/17398Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    4f97ec08
sinit.go 28.4 KB