[HN Gopher] Optimizing Guile Scheme
       ___________________________________________________________________
        
       Optimizing Guile Scheme
        
       Author : avvvv
       Score  : 120 points
       Date   : 2024-09-20 11:28 UTC (5 days ago)
        
 (HTM) web link (dthompson.us)
 (TXT) w3m dump (dthompson.us)
        
       | orliesaurus wrote:
       | As soon as I saw the title, I thought of the streetfighter
       | character, but this was actually an interesting read on a
       | programming language, I had never heard of before
        
         | abound wrote:
         | A prominent use of Guile is as the configuration language for
         | Guix, GNU's version of Nix
        
           | pxc wrote:
           | It's the official GNU extension language, so it's fairly
           | widely used in the GNU world I think.
           | 
           | It's also the language of the init system/service manager on
           | GuixSD (the full OS distribution based on Guix), GNU Shepherd
           | (a.k.a. dmd), and IIRC their initrd runs a Guile program
           | instead of a shell script.
        
         | bitwize wrote:
         | The slogan I've proposed for the language is "Guile goes with
         | everything." Because Guile was designed from the outset to run
         | embedded or standalone, and to transpile other extension
         | languages to Scheme or a Scheme-compatible representation, I
         | think that fitting. See: https://knowyourmeme.com/memes/guiles-
         | theme-goes-with-everyt...
        
           | davexunit wrote:
           | I think the Guile community of yore would have no idea what
           | Street Fighter was but now we should embrace it as long as
           | Capcom doesn't get mad.
        
             | bitwize wrote:
             | The other Scheme environment I use regularly is Gambit. So,
             | reppin both Marvel and Capcom.
        
           | fwip wrote:
           | Should it be "Guile Scheme goes with everything" for the
           | rhyme?
        
       | pjmlp wrote:
       | Great overview on how to approach improving code performance,
       | without going down the usual route of rewriting into something
       | else.
        
       | throwaway17_17 wrote:
       | Solid blog overall and I think it is pitched at the right level
       | of granularity for the topic. However, if I were offering
       | criticism, the place I think more detail would be super
       | interesting is the 'Please Inline' section. In particular, I
       | would really be interested in a slightly more detailed
       | description of the optimizer's algorithm for inlining. I think
       | the "define_inlinable" macro is a great example of macro usage,
       | but it is clearly a way to circumvent the inliner's apparent
       | short comings. I would like to be able to understand what
       | heuristic the optimizer is using to see if there is a sensible
       | default function construction style/idiom that is more appealing
       | to the optimizer for inlining. However, I am reminded of the
       | inlining discussion in Chandler Carruth's talk (Understanding
       | Compiler Optimization) from a few years ago where he discusses
       | how obscure and seemingly arbitrary, in general, inlining
       | heuristics and their optimization passes are in practice. [1]
       | 
       | 1 - https://youtu.be/FnGCDLhaxKU?si=J3MhvJ-BmX5SG2N6&t=1550
        
         | davexunit wrote:
         | A walkthrough of Guile's optimization passes and the inlining
         | heuristics would be great. I've been meaning to do a "part two"
         | here but you know how these things go.
        
       | atemerev wrote:
       | These sorts of optimizations can and should be handled by a
       | (sufficiently smart (tm)) compiler.
       | 
       | Common Lisp/SBCL is usually sufficiently smart. I know not
       | everyone likes Common Lisp, but at least I would have tested it
       | with something more performant that Guile, like Chicken Scheme
       | (my favorite!), Chez Scheme, etc.
       | 
       | I like Guile and its purpose as a universal scripting language.
       | However, its performance issues are well known. Even compared to
       | other scripting-first languages (Lua, Perl, Python etc).
        
         | throwaway17_17 wrote:
         | I think that is why this blog is particularly interesting to
         | me. As one of the other comments to this posting said, it is
         | nice to see an analysis/detailed description of working to
         | optimize code where the first step is not to rewrite in a
         | language with a presumed better performance baseline. Also, I
         | think there is also some props to be given for continuing to
         | work within Guile's somewhat spartan tooling to do the
         | optimization work, instead of switching to a language that may
         | have more/better tooling for the task.
         | 
         | Not to take away from the general comparisons between various
         | Lisp flavors and between various scripting languages (an
         | activity I engage in quite often), but your lead off line is
         | more prescriptive than I find advisable. I don't think a
         | blanket statement that optimizations of runtime behavior of
         | code "should" only be done via a compiler. Some devs enjoy the
         | work, others have varied reasons for doing performance
         | sensitive work in a given language/environment. But at the end
         | of day, doing optimization is a valid usage of developer effort
         | and time if that developer judges it so.
        
         | eru wrote:
         | Isn't Racket the 'default' Scheme? (Even though it's no longer
         | called Scheme.)
        
           | medo-bear wrote:
           | No
        
           | umanwizard wrote:
           | Extremely easy interop with native code is the main selling
           | point of guile IMO. You just link in guile as a library and
           | can have C code call scheme code and vice versa. Makes it
           | great for any native program that needs an embedded scripting
           | language (much like Lua). Does Racket support that use-case?
        
           | mepian wrote:
           | At this point it's a separate language from Scheme. I think
           | Chez Scheme tends to be the "default" recommendation.
        
           | tmtvl wrote:
           | I don't think there's a real 'default' Scheme, like Chez is
           | probably the implementation which generates the fastest code,
           | but if I'm not mistaken it only implements the R6RS spec,
           | Guile is quite performant and supports both R6RS and R7RS
           | Small, Chicken has a bunch of libraries (the 'eggs'), but I
           | think it's R5RS (I may be wrong), and of course GNU/MIT
           | Scheme is what you want to follow along with MIT publications
           | working in Scheme (like Structure and Interpretation of
           | Computer Programs, Structure and Interpretation of Classical
           | Mechanics, and The Art of the Propagator). There's also
           | Gauche, which I believe is the most conformant implementation
           | to the various Colour Dockets for R7RS Large (Gerbil may also
           | be fully conformant).
        
             | wbl wrote:
             | Racket is now built around Chez.
        
             | gus_massa wrote:
             | You can download a package to use R7RS Small in Racket.
             | https://github.com/lexi-lambda/racket-r7rs
        
         | davexunit wrote:
         | Guile has come a long way in the past decade or so! I think
         | your info is quite out of date. Guile's compiler performs a
         | number of state of the art optimizations. It compiles to
         | bytecode so native code compilers like Chez win the race,
         | naturally. The JIT is pretty good, though! Native compilation
         | is on the roadmap for Guile, but maybe somewhat surprisingly
         | we're getting AOT compilation to WebAssembly first.
         | https://spritely.institute/hoot/
        
           | armitron wrote:
           | It's still much much slower than SBCL which is not surprising
           | given the time & effort that went into the latter. User-
           | guided optimizations (type declarations, stack allocation,
           | intrinsics, machine code generation) in SBCL are also more
           | flexible and better integrated.
        
             | davexunit wrote:
             | Yup, SBCL is quite amazing!
        
         | tmtvl wrote:
         | I switched from Guile to SBCL because I really like having
         | things such as (declare (inline my-function)) and (declare
         | (type Double-Float x y z)). Now if only it had case-lambda,
         | named let, and a better deftype which can specify members of
         | classes and/or structs.
        
         | whartung wrote:
         | Part of the problem is that raw Scheme is spectacularly
         | underspecified.
         | 
         | It also doesn't help that Schemes like Guile are also
         | interactive. The domain of an interactive language and a
         | "compiled" language are quite different.
         | 
         | Given the entirety of the program made available to the
         | compiler all at once, there are high level derivations that can
         | happen notably through flow analysis to let the compiler make
         | better decisions. But do that in an interactive environment
         | when the rug can be pulled out of any of the assumption the
         | compiler made, and things get messy quite quickly.
         | 
         | One interesting tidbit for Java is that the developers of the
         | compiler advocate "idiomatic" Java. Simply, write Java like
         | Java, and don't try to trick the compiler. Let the compiler
         | developers trick the compiler.
         | 
         | That's evident here in this article when they wrote the
         | function that tests the types of the parameters. Raw Scheme,
         | naturally, doesn't allow you to specify parameter types, not
         | the way you can in Common Lisp, for example. And, either Guile
         | does not have an specific extension to support this, or simply
         | the compiler looks for this type checking pattern at the top of
         | a function to make optimization determinations. On the one
         | hand, it could be more succinct with a specialized facility,
         | but on the other, this is "just Scheme".
         | 
         | So, in effect by checking for the type of the variable, they're
         | implicitly declaring the type of the variable for the
         | "sufficiently smart" compiler to make better decisions.
         | 
         | The counter example is the "define-inline" construct, and thus
         | not standard Scheme (though readily replaced by a "no-op" macro
         | if one was interested in porting the code).
        
       | munificent wrote:
       | I have such mixed feelings about dynamically typed languages.
       | I've designed a whole pile of hobby programming languages, and
       | dynamically typed languages are at least an order of magnitude
       | simpler to design and for users to learn and start using.
       | 
       | At the same time, they inevitably seem to lead to user stories
       | like this where a user really does know exactly what types
       | they're working with and wants the language to know that too (for
       | performance or correctness), and they end up jumping through all
       | sorts of insane hoops to get the optimizer to do exactly what
       | they want.
        
         | sctb wrote:
         | I like dynamic languages too. But I don't like the idea of
         | "optimization", and I would be super interested in a dynamic
         | language that didn't attempt to divorce performance from
         | correctness. The worst part about jumping through insane hoops
         | to enchant the optimizer is that it can all go wrong with the
         | tiniest change--a flag here, a different usage pattern there, a
         | new version, etc., and suddenly your program doesn't do what
         | you need it to, as though an operation taking 1000x longer is
         | just a matter of degree.
        
           | munificent wrote:
           | I agree completely.
           | 
           | At the same time, no one wants their code to run 100x slower
           | than it would in any typical statically typed language.
           | Unoptimized dynamic languages are _sloooooow_.
        
         | zem wrote:
         | stanza (https://lbstanza.org/) is a very interesting experiment
         | in designing for gradual types rather than retrofitting them
         | onto a dynamic language
        
         | davexunit wrote:
         | I'm happy with dynamic languages for almost everything I do and
         | generally do not want to sacrifice flexibility, which is the
         | price to pay for a static type system. However, certain parts
         | of a program become more crystalline over time, whether for
         | performance or correctness reasons, and being able to express
         | those parts using a static type system makes a lot of sense.
         | PreScheme [0] is an example of a statically typed Scheme that
         | composes with the host Scheme. I'd like to see more work in
         | this direction as Scheme already works well as a multi-paradigm
         | language.
         | 
         | [0] https://prescheme.org/
        
         | cardanome wrote:
         | I think Common Lisp got it exactly right. Strongly typed
         | dynamic language where you can optionally specify types for the
         | extra performance/correctness if need be (especially with
         | SBCL).
         | 
         | Honestly, I think weak typing is more of an issue than dynamic
         | typing and people cry for static types when they suffer mostly
         | from the former.
         | 
         | Dynamic typing is great because it allows you to have extremely
         | complex types for basically free. It allows for insane
         | expressiveness. It also makes prototyping much easier and does
         | not force you into over-specifying in you types early on. In
         | dynamic language most of your types are the most general type
         | that would work by default while static types forces you to use
         | very specific types (especially when lacking structural
         | typing.)
         | 
         | If you want to allow just half the expressiveness of dynamic
         | languages in your static language you will quickly find huge
         | complexity with dependent types, long compile time, cryptic
         | error messages and whatnot.
         | 
         | Generally, I think gradual typing is rising in popularity for
         | good reason. It allows for quick prototyping but also to drill
         | down on your types when you want to. Best of both worlds.
        
       | samatman wrote:
       | If you want to read just an enormous amount of well-written
       | bloggage about optimizing Guile Scheme, this is the spot:
       | https://wingolog.org
       | 
       | Andy Wingo is the maintainer and I get a kick out of everything
       | he posts.
        
         | davexunit wrote:
         | Andy's blog is on another level. He's also leading the Hoot
         | project to compile Guile to WebAssembly and I work with him on
         | that and try to absorb whatever compiler knowledge I can while
         | doing so.
        
       | exitb wrote:
       | You probably shouldn't do those things. The point of a high level
       | language is to not have to think about such details. If you can't
       | get the performance you need, you should use a different tool,
       | instead of trying to circumvent implicit limitations.
        
       | anthk wrote:
       | I prefer Common Lisp with SBCL and Lem, but this is good too.
       | 
       | On SICP, Guile badly needs a module for the picture language from
       | the book (and srfi-203 + srfi-216).
        
       ___________________________________________________________________
       (page generated 2024-09-25 23:00 UTC)