Live data from Hacker News

The Swift compiler is slow due to how types are inferred

danielchasehooper.com

91–100 of 229 posts

Re: The Swift compiler is slow due to how types are inferred

#91

Earlier quoted context omitted.

Python real strength is the speed it can be taught, read and written.

Python’s real strength is that it has a vast ecosystem of uber powerful libraries written in C/C++.

Shared by any language with FFI capabilities.

Re: The Swift compiler is slow due to how types are inferred

#92

Earlier quoted context omitted.

I wouldn't describe Swift itself as having so much potential: I loved it and advocated for it, for years. After getting more experience on other platforms and having time to watch how it evolved, or didn't as per TFA, it's...okay to mediocre compared to peers - Kotlin, Dart, Python come to mind. If Foundation was genuinely cross platform and open source, that description becomes more plausible for at least some subse…

What is there to say in favor of Dart? Isn’t it a “good enough” middle-of-the-road language?

Pretty much, which I love. Opinionated TL;Dr: Kotlin without the duplicates of Java classes, or 20 different inscrutable functional operators. Swift without the compile times and architecture astronaut stuff that infected stuff built on it and makes apple reinvent it every 2-4 years, c.f. async/SwiftUI. Genuinely cross platform, both in terms of code* and UI** It's indistinguishable from native in the way that's meaningful to users (note it's AOT on not-web, not JIT, and does a bunch of obvious stuff, use the platform text renderer, scollbars, scroll velocity, etc)

* I'm too old now, 36, and you have no idea how much I roll my eyes internally at hopeful invocations of 'man if only Swift was cross platform / look apple did this so swift is coming cross platform. All the "SwiftUI web is clearly coming" wish casting from big names in the Apple dev community who should have known better broke me.

** the mish mash of bad, competing solutions to bringing iOS UI cross Apple platforms forfeits the core premise of an Apple-values inheriting dev: I'm infinitely better off having a base UI engine that renders the same stuff on each platform than a shim that renders and acts differently

Re: The Swift compiler is slow due to how types are inferred

#93

Earlier quoted context omitted.

Im surprised to see Python in that list. Swift being type safe and Python not puts Swift miles ahead.

One of those awkward things where I don't like it, and wouldn't go back to nulls that blow up. But as far as being the right tool/accessible it ended up winning use cases where I expected scripting and Playgrounds to have mindshare

Playgrounds is so painfully slow that you can't really "play" with it at all.

Re: The Swift compiler is slow due to how types are inferred

#94
post #57

Earlier quoted context omitted.

I'm not an expert on the theory, but OCaml has a very fast compiler and while it is (almost) capable of fully reconstructing the types from a program with no annotations, it doesn't have to deal with ad-hoc polymorphism and takes some shortcuts like weak polymorphism when it gets too hard: https://www.ocaml.org/manual/5.2/polymorphism.html

Try this: let f0 = fun x -> (x, x) in let f1 = fun y -> f0(f0 y) in let f2 = fun y -> f1(f1 y) in let f3 = fun y -> f2(f2 y) in let f4 = fun y -> f3(f3 y) in let f5 = fun y -> f4(f4 y) in f5 (fun z -> z) Lifted from https://dl.acm.org/doi/pdf/10.1145/96709.96748 via Pierce, Types And Programming Languages.

But that's just a type that is huge. I didn't want to wait for the evaluation, but if I drop the f5 out, I got a type that is 1.6 megabytes long when printed without spaces.

It's still very fast for "normal size" types. That reduced version compiles in 151 milliseconds.

Re: The Swift compiler is slow due to how types are inferred

#95
post #32

It's really hard for me to read past Lattner's quote. "Beautiful minimal syntax" vs "really bad compile times" and "awful error messages". I know it's not helpful to judge in hindsight, lots of smart people, etc. But why on earth would you make this decision for a language aimed at app developers? How is this not a design failure? If I read this article correctly, it would have been an unacceptable decision to make u…

> aimed at app developers I'm a native Swift app developer, for Apple platforms, so I assume that I'm the target audience. Apps aren't major-league toolsets. My projects tend to be fairly big, for apps, but the compile time is pretty much irrelevant, to me. The linking and deployment times seem to be bigger than the compile times, especially in debug mode, which is where I spend most of my time. When it comes time to…

I tried to fix a bug in Signal a few years ago. One part of the code took so long to do type inference on my poor old Intel MacBook that the Swift compiler errored out. I suppose waiting was out of the question, and I needed a faster computer to be able to compile the program.

That was pretty horrifying. I’ve never seen a compiler that errors nondeterministically based on how fast your cpu is. Whatever design choices in the compiler team led to that moment were terrible.

Re: The Swift compiler is slow due to how types are inferred

#96
post #84
post #70

Earlier quoted context omitted.

> One of the interesting tradeoffs in programming languages is compile speed vs everything else. Yes, but I don't think that compile speed has really been pushed aggressively enough to properly weigh this tradeoff. For me, compilation speed is the #1 most important priority. Static type checking is #2, significantly below #1 and everything else I consider low priority. Nothing breaks my flow like waiting for compilat…

I think this is a false choice. It comes from the way we design compilers today. When you recompile your program, usually a tiny portion of the lines of code have actually changed. So almost all the work the compiler does is identical to the previous time it compiled. But, we write compilers and linkers as batch programs that redo all the compilation work from scratch every time. This is quite silly. Surely it’s poss…

> But, we write compilers and linkers as batch programs that redo all the compilation work from scratch every time.

I don't think that there are that many production level compilers that don't perform the kind of caching that you're advocating for. Part of them problem is what the language semantics are. https://www.pingcap.com/blog/rust-huge-compilation-units/ gives an example of this.

> Surely it’s possible to make a compiler that takes time proportional to how much of my code has changed, not how large the program is in total.

Language design also affects what can be done. For example Rust relies a lot on monomorphisation, which in turn makes much harder (not necessarily impossible) to do in-place patching, but a language like Java or Swift, where a lot of checks can be relegated to runtime, it becomesuch easier to do that kind of patching.

I think that there's a lot left to be done to get closer to what you want, but changing a compiler that has users in such an extensive way is a bit like changing the engine of a plane while it's flying.

Re: The Swift compiler is slow due to how types are inferred

#97

I'm suspicious about the truth of this claim. I don't think bidirectional typechecking is the problem in itself: the problem trying to do type inference when you have some extremely flexible operator overloading, subtyping, and literal syntax features. It's these "expressive" features which have made type inference in Swift far more computationally complex, not type inference itself. And certainly not bidirectional t…

I'd trade type inference for expressibility (function and operator overloading in particular). But this seems to currently be a heretical opinion.

Rust took the other road:

    error[E0277]: cannot add `i64` to `i32`
        1i32 + 2i64;
             ^ no implementation for `i32 + i64`
It bothered me at first, there are a lot of explicit annotations for conversions when dealing with mixed precision stuff. But I now feel that it was the exactly correct choice, and not just because it makes inference easier.

Re: The Swift compiler is slow due to how types are inferred

#98

Earlier quoted context omitted.

I wouldn't describe Swift itself as having so much potential: I loved it and advocated for it, for years. After getting more experience on other platforms and having time to watch how it evolved, or didn't as per TFA, it's...okay to mediocre compared to peers - Kotlin, Dart, Python come to mind. If Foundation was genuinely cross platform and open source, that description becomes more plausible for at least some subse…

What is there to say in favor of Dart? Isn’t it a “good enough” middle-of-the-road language?

It is truly cross platform, unlike Swift, has great UI going for it that you can use everywhere and improved greatly as a language in recent years while Swift continued siloing itself in Mac world.

Dart might not break world records for most innovative or performant general purpose language, but it’s a completely different language from 6 years ago.

Re: The Swift compiler is slow due to how types are inferred

#99
post #84
post #70

Earlier quoted context omitted.

> One of the interesting tradeoffs in programming languages is compile speed vs everything else. Yes, but I don't think that compile speed has really been pushed aggressively enough to properly weigh this tradeoff. For me, compilation speed is the #1 most important priority. Static type checking is #2, significantly below #1 and everything else I consider low priority. Nothing breaks my flow like waiting for compilat…

I think this is a false choice. It comes from the way we design compilers today. When you recompile your program, usually a tiny portion of the lines of code have actually changed. So almost all the work the compiler does is identical to the previous time it compiled. But, we write compilers and linkers as batch programs that redo all the compilation work from scratch every time. This is quite silly. Surely it’s poss…

Agreed. For example, Julia (which is a compiled language) has a package called Revise, which provides incremental compilation. A cold start on a package / project / script will take awhile, and even when dependencies are precompiled, but the code you're working on is not, REPL startup takes noticeable amounts of time.

But once you have your REPL prompt, it's just: edit code, test it. Revise figures out what needs recompiling and does it for you. There are some limitations, most notably, any redefinition of a struct requires a reboot, but it's a great experience.

A lot of the current work going into the Zig compiler is to greatly increase the compile time of debug builds, by cutting the LLVM dependency, and then add incremental compilation. I'm looking forward to the fruits of that labor; I don't like to wait.

Re: The Swift compiler is slow due to how types are inferred

#100

Earlier quoted context omitted.

Most languages are forced to choose between tooling speed and runtime speed, but Python has historically dealt with this apparent dichotomy by opting for neither. (⌐▨_▨)

Python real strength is the speed it can be taught, read and written.

I wish this were true. I've used Python professionally for more than a decade and I still don't consider myself an expert (but I consider myself an expert in Go despite having only used it professionally for a few years). A few things off the top of my head that I still don't understand expertly and yet they chafe me quite often: how imports are resolved, how metaclasses work, how packaging works, etc.

And on the beginner end, even simple things like "distributing a simple CLI program" or "running a simple HTTP service" are complicated. In the former case you have to make sure your target environment has the right version of Python installed and the dependencies and the source files (this can be mitigated with something like shiv or better yet an OS package, but those are yet another thing to understand). In the latter case you have to choose between async (better take care not to call any sync I/O anywhere in your endpoints!) or an external webserver like uwsgi. With Go in both cases you just have to `go build` and send the resulting static, native binary to your target and you're good to go.

And in the middle of the experience spectrum, there's a bunch of stuff like "how to make my program fast", or "how do I ensure that my builds are reproducible", or "what happens if I call a sync function in an async http endpoint?". In particular, knowing why "just write the slow parts in multiprocessing/C/Rust/Pandas" may make programs _slower_. With Go, builds are reproducible by default, naively written programs run about 2-3 orders of magnitude faster than in Python, and you can optimize allocations and use shared memory multithreading to parallelize (no need to worry if marshaling costs are going to eat all of your parallelism gains).

"Python is easy" has _never_ been true as far as I can tell. It just looks easy in toy examples because it uses `and` instead of `&&` and `or` instead of `||` and so on.

Post reply on HN