4 ms·
Also, it produces binaries (probably similar to golang) which are a reasonable size considering there is a garbage collector. No giant interpretors or VMs requi
by Can_Not 6y ago
Also, it produces binaries (probably similar to golang) which are a reasonable size considering there is a garbage collector. No giant interpretors or VMs required.
And macros.
- rjzzleep 6y agoWhat is the compilation speed like? EDIT: also forgot to ask if Crystal has a "killer app" yet? Ruby had Rails, Python had scipy/pandas(several others), Rust had servo etc.
- unixhero 6y agoWhy is that important given Moores law and fast developer workstations? Everyone seems so preoccupied with compile speed for Crystal.
- pantulis 6y agoThe question is legit, though.
- unixhero 6y agoSure enough. Still wondering about why.
- pantulis 6y agoAlso, this observation: in terms of developer time, compiled languages (a la Crystal, Go, Rust...) the disadvantage of compile time should be offset by much faster local test runs and even CI builds.
- pantulis 6y agoFor a sufficiently big codebase, that is.
- atleta 6y agoYou'll usually just run a few tests if you are working on a specific feature and only run more of them when you think you are done. So most of the time there will be too little difference to make up for the increased compilation time. Also, you are comparing compiled languages to interpreted ones, but the GP talked about differences between compilation time (i.e. compiled languages). And others are also comparing it to e.g. go (compiled but quick to compile).
- pantulis 6y agoYou are totally right.
- yberreby 6y agoBecause high compilation times can be a major turnoff, and the single-threaded performance of a beefy developer workstation is not that much higher than that of a regular machine. You can't always throw more cores at a problem, and Moore's Law hasn't exactly been holding true lately.
- reitanuki 6y agoMoore's law has stopped, and not every developer's workstation is 'fast'.
- andi999 6y agoIt is a huge difference if you can compile is less then a second (giving you almost repl functionality) or if you have to resort to nightly builds for large projects. Even 15 minute builds hamper development.
- dexterlagan 6y agoTwo kinds of people: - people who routinely compile huge code bases; - people who compile an OS. C is still here because it compiles UNIX fast.
- rjzzleep 6y agoEven there compile speeds make a difference. The linux kernel is quite slow to compile, but when you make changes it doesn't take that long because it generally just rebuilds a file or two fairly quickly because of the way dependencies and changes are handled. If every driver change would require 15 minutes to build it wouldn't be nearly as popular as a platform. I don't know how opensolaris kernel builds are, but they're not nearly as simple to wrap your head around as the linux kernel. As a result the level of participation is quite low. Of course this is more a build issue than it is a language issue in this case. But yes as you said the compile speed on the linux kernel is partly because it's C and not C++
- Cthulhu_ 6y agoCompile speed is part of Developer Experience, and one of the most important aspects thereof is the feedback cycle. I want to see the results of my code changes as fast as possible, and the performance of my hardware is rarely ever the bottleneck.
- m12k 6y agoI think if you've been bitten by compilation times in e.g. Scala or C++, then compile speed is something you end up caring about. When it comes to modern static languages, it seem like there's a tradeoff where providing all the abstractions and ergonomics to make you not miss any functionality from dynamic languages will instead expand compilation times and make you miss the instant feedback of an interpreted language. Or give up on that and make the language much simpler and more limited, and you get fast compilation (e.g. Go). So I think people are looking for the holy grail of a language with both ease of use, extensive ergonomics and abstractions, while maintaining fast compilation times. So anytime a candidate comes along they ask about the parts of that equation that are not in the bullet list.
- pjmlp 6y agoC++ compile speeds can be easily improved when using binary libraries, incremental compilation, incremental linking, and hopefully modules will help as well. Energize C++ and VA C++ v4.0 showed the way of a Smalltalk like experience for C++, the tools just need to catch up with the past. VC++ and C++ Builder are on the good path for it.
- andi999 6y agoDon't forget pimpl.
- rad_gruchalski 6y agoAdding to that, sbt also supports incremental compilation with zinc.
- christophilus 6y agoOnce you've gotten used to the speed of something like OCaml and Go, it's really hard to go back. Rust feels excruciating to me, even though I like the language.
- exikyut 6y agoWell, I have ADHD. I've found the most effective approach (on top of treatment) that helps me retain focus is reexec-on-save, a la `while :; do tput clear; $thing; inotifywait -q -e moved_to .; done`. I usually have a dozen of those in old shell histories (^R FTW). (Ha, my laptop actually has exactly 12, and my other machine has 23 - although ignoredups is off...) $thing might be `bash ./script.sh` (because my text editor's atomic rename doesn't understand execute bits >.>), `php script.php` or `gcc -O0 script.c && ./script`. (Also, as an aside I used to use `-e close_write $file` until I realized watching even giant directories is equivalently efficient to watching a file.) Shell scripts (the small kind that run few subprocesses) are typically fast. Likewise, small C programs of <1000-2000 lines compile just about instantly on modern hardware; and where modern hardware isn't available and what I'm trying to do doesn't leverage too many libraries or whatnot, tcc has been able to swing the balance firmly in my favor in the past, which has been great. But for better or worse, PHP is currently the language I use the most. Because it's faster than Python and Ruby. A while back I wanted to do a bit of analysis on a dataset of information that was only published as a set of PDF documents... yayyy. But after timidly gunzipping the stream blocks and googling random bits of PDF's command language ("wat even is this"), I discovered to my complete surprise that it was trivial to interpret the text coordinate system and my first "haha let's see how bad this is" actually produced readable text on pretty much the first go. (To be pedantic, step #-1 was "draw little boxes where the text should be", step #0 was "how to x,y correctly" (with a side serving of "...those boxes look quite reasonably positioned..."), and step #1 was "replace boxes with texWHAT it worked?!") With rendering basically... viable (in IIRC 300-500 LOC O.o), the next step was the boring stir-the-soup-for-144-hours bespoke state machine that cross-correlated text coordinates with field meanings ("okay, that's a heading, and the next text instruction draws the field value underneath. OK, assert that the heading is bold, the value is not, and they're both exactly the same (floating-point) Y position"). While that part took a while, it was mostly extremely easy, because I was pretty much linearly writing the script "from start to finish", ie just chipping away at the rock face of the task at hand until I processed an entire document, then the next document ("oh no"), then the next one ("ugh") and so forth ("wait, the edge cases are... decreasing? :D"). My workflow was pretty much founded entirely on the above-noted method where I would re-exec the script from scratch upon save. Loading/gunzipping a given PDF and getting to the point where the little pipeline would crash would typically complete well before I had a chance to release the CTRL key after hitting CTRL+S. So while the process was objectively quite like stirring soup, it did not feel like that at all and I was able to kind of float a bit as my brain cohesively integrated the mental model of the architecture I was building without any distractions, pauses or forced context switches getting jammed in the mental encoding process like so many wrenches. Soon 15 documents were handled correctly, then 20, then 30, then 100 ("oooh, if all the items on the page add up exactly right it pushes line 2 of the summary heading down to the second page! Hmmm... how on earth to special-case that without refactoring to look at more than 1 page at a time..."), and then I hit some sort of threshold and it suddenly just started ticking through PDFs like crazy without asserting. Which was both awesome and a Problem™: the thing ran at something like ~60 PDFs/sec, and while jumping to just after the last successfully-processed PDF on restart worked great when the code crashed constantly, now I was sitting spinning for tens of seconds, getting distracted as I anticipated the next crash. ADHD(R)(TM). I wasn't surprised to learn from htop that the script was disk-bound; for some reason my ZFS mirror setup will happily read sequentially at 200MB/s, but thousands-of-tiny-files situations are... suffice to say apt unconditionally takes 60 seconds to install the smallest thing, unless the entire package db is in the FS cache. I'm not sure why. The PDFs were sharded sanely, but they were still in separate files. So I decided to pack them all into a giant blob, and since there weren't too many PDFs and they were numbered sequentially I used a simple offset-based index at the front of the blob where `fseek(data_start + (<PDF ID> * 4)); $o = fread(4); fseek($o);` would give me random seeking when I needed it, or I could just fseek() to data_start and start reading directly. Reading the blob instead promptly pegged a single CPU core (yay!), and gave me IIRC ~150-200+ PDFs/sec. This was awesome. But I was still just a tiny bit curious, so after googling around for a profiler and having a small jawdrop moment about SPX (https://github.com/NoiseByNorthwest/php-spx https://github.com/NoiseByNorthwest/php-spx), I had a tentative look at what was actually using the most CPU (via `SPX_ENABLED=1 php ./script.php`, which will automatically print a one-page profile trace to stdout at graceful exit or ^C). Oh. The PDF stack machine interpreter is what's taking all the CPU time. That tiny 100 line function was the smallest in the whole script. lol So, I moved that function to the preprocessor/packer, then (after some headscratching) serialized the array of tokenized commands/strings into the blob by prefixing commands with \xFF and strings with \xFF\xFE\xFF so I could explode() on \xFF and tell commands from strings by checking if the previous entry was \xFE (and just skip entries of '\xFE' when I found them) :D. Then I reran the preprocessor to regenerate the pack file. $ php convert_dlcache.php Scanning... 24/66060 67,927 entries [4.27 sec] Sorting... 10013-343271 [1.61 sec] data_start=1373094 * 67,920/67,927 99.99% 83/s 00:00 13:58 343259 Thankfully I've only needed to run the preprocessor rarely, like for example I only needed to run it twice today because it promptly truncated its pack file when I accidentally reran it after the first run (yay). Yes, it really does take ~14 minutes, and yes, there are just under 70,000 PDFs. Then I reran the pipeline script. $ php conv2.php 67,927/67,927 890/s 01:16 00:00 343271 Complete Oh. 900 PDFs/sec. Uh, what happens if I... set up a simple pcntl_fork() + stream_socket_pair() multi-process worker system...? $ php conv2.php Reading... done 4 workers, (16,982 x 3) + (16,981 x 1) 62,162/67,927 1,800/s (469/s 166319, 444/s 237743, 442/s 302338, 444/s 340327) 00:34 00:03 ^C "Oh. Okay." ":D" (The workers disappear from the output as they complete, so I ^C'd it just before they all exited, at 3 seconds left.) So. 68,000 PDFs/sec on a not particularly amazing 3.3Ghz i3-3220 with 1600MHz RAM. PHP 8's JIT is aweso--wait, is the JIT actually on? Oh. It's off by default. $ php -dopcache.enable_cli=1 -dopcache.jit_buffer_size=32M conv2.php Reading... done 4 workers, (16,982 x 3) + (16,981 x 1) 58,206/67,927 2,537/s (669/s 163803, 623/s 230254, 619/s 300420, 627/s 338470) 00:22 00:03 *Blinks* (In small voice) "I am processing/unit-testing 68k documents in 22 seconds. At over two and a half thousand PDFs a second." I also noticed that PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command 31511 i336 20 0 276M 19864 5736 R 100. 0.2 0:18.25 php conv2.php 31513 i336 20 0 276M 19856 5732 R 100. 0.2 0:18.35 php conv2.php 31512 i336 20 0 276M 19728 5600 R 100. 0.2 0:18.32 php conv2.php 31510 i336 20 0 276M 19764 5648 R 97.7 0.2 0:18.03 php conv2.php 31509 i336 20 0 275M 34072 20036 S 0.7 0.4 0:00.19 php conv2.php the workers are only using 20MB RAM each. This is with object deferencing going on, after I kinda started going crosseyed and properly moved my JBOGF (Just a Bunch of Globals and Functions) into a proper class (albeit a static one, since I'm still learning, and construction/deconstruction would probably slow things down too). I also note that with the JIT off, VIRT is 115M, RES is 16,312K and SHR is 2,412K for all workers, with the master taking 29M RES and 15M SHR. -- Why'd I write all this?! To make the point that a) live reexec on save is an awesome programming model when it can be applied, and b) PHP is my incredibly awkward gold standard reference, lol. (In rerunning everything for this post I discovered the JIT and learned my script could go even faster!) I've been keeping vague tabs on recent language developments from a bit of a distance for a while now, and am very interested to dig into Rust and Zig's incremental compilation capabilities at some point. Based on what I'm hearing I don't know if I should just go dive in yet though - to be entirely honest, there are multiple realms of applications I simply cannot write in PHP - including things as simple as console CLIs, because the neccessary TTY I/O control (eg, turning TTY echo off and reading 1 char at a time) remain unavailable (see also: multiple years-old long-forgotten bugs/feature requests). I don't really want to discover what's possible only to find myself between a rock and a hard place as my programs start to grow and I hit invisible quadratic brick walls that persist after I enable every "fastest possible" setting the language offers. That happened a few years ago when I tried to play around with FLTK in C++; once build times were around the 3-4 second mark (*with* -O0 and precompiled headers), regardless of the fact that I'd been working on the project for enough time I was invested in it, I just gave up. Much more recently I installed .NET Core the other day to run and dissect a small F# program. Running `dotnet fsi` cold took 5 seconds to reach a REPL prompt (ouch), and while warmed-up reruns would only take 1 second, I found actually loading a ~300-line program would take a non-reducible ~4-5 seconds. Everyone's different, and sometimes things people say can look crazy, or stupid, or "...how even...", but they can still be true for that person. For me, waiting 4 seconds for an interpreter/runtime/etc to reach a useful milestone such as "I can actually interact at all with it" is untenable. Yup. I go straight to "I've waited for this thing to do the thing 200 times today <cartoon punching fight cloud>" after the 3rd pause. I am utterly incompatible with the Old Guard "code's compiling!" way of doing things. It puts me straight into defensive not-in-my-comfort-zone mode. Completely open-minded about Crystal, which I've heard repeatedly good things about. Yes, of course, I haven't tested it (yet), again because I don't want to go "wow this is awesome... except I don't have the patience for it :(". The status quo noted above remains an actively unsolved problem; trying to figure out how many interesting things I can wedge into the "focusable space" defined by "how big I can make my program before the programming languge slows down" is getting boring. Perhaps I'm just stuck here because I'm using older(ish) hardware, and once I finally figure out that problem I'll suddenly realize all of this deep analysis was unnecessary. heh
- Sathi 6y agoYes, there are lucky and amber frameworks. Hopefully, one of them will make crystal more popular/mainstream.