22 ms·
Delphi 2 can compile large .pas files at 1.2M lines per second
- oso2k 6y agoNot surprised [0]. Pascal was always very fast to compile, especially with Borland tools. [0] https://prog21.dadgum.com/47.html https://prog21.dadgum.com/47.html
- giancarlostoro 6y agoTheres a video of this on YouTube it always fascinated me. I asked an old timer about it he said it was designed to be simple to compile and the compiler was in Assembly. Not sure how truthful this is would love to hear more about how and why its so fast. I would love to someday see FreePascal be just as fast. Its a shame Borland didnt try to make some sort of collaboration between them and FPC. I am sure FPC would welcome some sort of joint effort you help us we help you kinda deal.
- pkaye 6y agoI think optimizations passes is what takes the most time in a compiler. Older compilers did a lot less.
- andi999 6y agoWell then at leastbwith -O0 should be similiar times achievable?
- TazeTSchnitzel 6y agoModern compilers are still pass-based with an optimisation-friendly IR even if you skip the actual optimisation passes. A single-pass compiler will be faster because it does not have the overhead of doing things in multiple passes.
- Touche 6y agoTurbo pascal was single pass, parse and compile.
- pkaye 6y ago-O0 still does some optimization from what I can find online. Maybe someone knows more specifics since the manual is pretty brief.
- guenthert 6y agoI can only confirm that -O0 performs some optimization, which can be annoying when single-stepping through the code (cough, cough) using a debugger. Hence gcc offers -Og to suppress those optimizations (not sure, whether that in itself causes some debugging info to be added though).
- aninteger 6y agoI think a very early Turbo Pascal was in assembly, but I would find that hard to believe of Delphi.
- tpmx 6y agoIt isn't that much of a stretch to believe that they kept most of the compiler in assembly. The language itself didn't change that much from Borland/Turbo Pascal 6.0/7.0 to Delphi iirc. Also, there was a source code leak about a decade ago of Turbo Pascal 6.0 that showed the compiler was still 100% x86 assembly. Just found it via Yandex - it was pretty hard to find with Google. (I only looked at the directory listings of the source code filenames just now, at some sourceforge-like site.)
- FullyFunctional 6y agoAs a young lad, I studied the internals of BLS Pascal (the great-grandfather of Turbo Pascal) and was blown away by the cleverness of much of the code. I had never seen such clever machine code before and have ever since considered Anders a bit of a genius.
- noir_lord 6y agoAnders isn't a 'bit of a genius' when it comes to language/runtime design he is straight up one of the geniuses. I'm 40, I've programmed since 87 and the languages I've truly loved using in the real world have always been Anders languages in some way (TP -> Delphi -> C#/.Net -> TypeScript) - he has amazing taste in what he implements and when - he just has an eye for practical languages that solve common problems nicely.
- jojobas 6y agoPascal compiles to some sort of bytecode doesn't it? One would think it's an easier task than all the fancy x86 business?
- oso2k 6y agoEarly Pascals did. P-Code [0] it was called. I don't think it was really about easy of compilation. It was about ease of portability, at least early on. [0] https://en.wikipedia.org/wiki/P-code_machine https://en.wikipedia.org/wiki/P-code_machine
- FullyFunctional 6y agoIt was and it was key to why Pascal became so successful. Porting the VM of the UCSD-p machine was so much easier than writing a new backend so Pascal spread like wildfire. I think I even saw a Commodore 64 port at some point.
- FpUser 6y agoNot compilers released by Borland/successors or Free Pascal. It is all native code.
- ablekh 6y agoGood old times ... Thank you for the nostalgic reminder.
- sippingjippers 6y agoNow let's compare performance after implementing 2 decades worth of missing program optimization techniques (edit: downvotes? I'm sorry to ruin the romanticizing, but surely it should come as no surprise that these old compilers aren't fast due to black magic)
- melling 6y agoI only want that on a few of my builds. Most days I could be happy with 1 second builds. Considering that I don’t have a million lines of code, I think 100,000 lines of code a second should cover it.
- Gibbon1 6y agoMy prat comment about C++ is the compiler writers are stuck in a trap. Because compiling C++ is slow they add optimizations to the compiler (also written in C++) to make the code faster. But that makes the compiler even slower. So they add even more optimizations to the compiler to make it run faster...
- higerordermap 6y agoNo. C++ is slow to compile due to some historical decisions like preprocessor. But the C++ standard committee has come to rely on optimizing compilers with powerful inliners and optimizers, to implement new "zero cost" [sic] abstractions as convoluted template libraries with lot of corner cases (neglecting incomprehensible error messages and debug build performance as well). Efficiently compiling C++ effectively __requires__ a top notch optimizer because of the disconnect between standards committee and implementers. Moreover, relying on optimizers often results in non obvious performance traps. The stupidity of standards committee and their sheer insistence on nothing but being able to sell more books every years is why even modern C++ is such a horrible development experience.
- ncmncm 6y agoThis description is absolutely at variance with the reality of C++ Standard activity. Compiler and Standard Library implementers are intimately involved in all phases of standardization. Book sales have much less effect than authors would like; they would prefer many fewer changes. Furthermore, C++ coding experience improves markedly with each new Standard, released on a 3-year cadence. C++20 is nicer than '17, which is nicer than '14, which is nicer than '11, which is much nicer than '03, which is a little nicer than '98. '23 will be nicer than all of them.
- W-Stool 6y agoIt is hard to emphasize enough now how the original Turbo Pascal was such a breakthrough in development tools for the PC. RIP Borland - for a while there you were really the business.
- pjmlp 6y agoHaving been there, I start to see some similarities the way JetBrains is attempting to go everywhere and replace OS vendors own IDEs and languages.
- laumars 6y agoRIP Pascal as well. Delphi wasn’t without it’s frustrations but Pascal was a far better language than people give it credit for these days.
- edwinyzh 6y agoWhy? See how Free Pascal Compiler is alive: https://github.com/graemeg/freepascal/commits/master https://github.com/graemeg/freepascal/commits/master And its IDE: https://github.com/graemeg/lazarus/commits/upstream https://github.com/graemeg/lazarus/commits/upstream And we have new versions of Delphi very year, with a free Community edition: https://beta.embarcadero.com/products/delphi/starter https://beta.embarcadero.com/products/delphi/starter PS, I myself write all my software with Delphi, and this is the newest one: https://docxmanager.com https://docxmanager.com - something that turns MS Word into something like WordPress :)
- eli 6y agoI cut my teeth on Delphi 2. Didn't realize how good I had it! Solid IDE that Just Worked right out of the box with point and click GUI builder. And the builds were fast and IDE responsive even on "average" hardware of the day.
- codeulike 6y agoAnd packaging and installation was a doddle, if I remember correctly. Everything just rolled up into one installable exe?
- squarefoot 6y agoDelphi was extremely fast, and later much heavier releases such as Delphi 4 still were a lot more fast back then on older machines than Lazarus/FreePascal is today on modern hardware. To give some figures, I've installed an old non legit version of Delphi 7 on Linux through Wine, and timed some compilation tests, from start of compilation to application running. Well, on Lazarus an empty form takes like 28 seconds to compile first time, or uncached, while from 2nd time on it takes from 2 to 3 seconds. Another form filled with objects takes 3 seconds on Delphi 7 uncached, and about 1 second cached. All this under Wine, i5 machine, mechanical disk drive; the difference is astounding. I wish Lazarus/Freepascal received some optimizations to get more close to the speed of Delphi.
- ibejoeb 6y agoI loved Delphi. And Borland and Borland-progeny products. I have a shrink-wrapped box of Turbo Pascal 7 for DOS. It's been long enough since physical acquisition of software that I'm not even sure how to say that. "Box of Turbo Pascal" seems awkward.
- randlet 6y agoA gift (c. 1997?) from my parents of a "box" of Turbo Pascal is easily one of the most influential moments of my life. It was such a great programming environment and the docs (books!) were fantastic and quite accessible. I'm still chasing the dragon of the feeling of programming I had back then.
- switchbak 6y agoAbsolutely. The rapid feedback from the near instant compile was so addictive. I would be in flow state for so long. If only I knew about unit tests back then. I really only get that these days with toy challenge problems. That might also have a lot to do with the nature of programming now. So much is based on googling known solutions and scouring examples, etc. Probably a better use of time, but you don't get the ego trip of feeling like a wizard.
- W-Stool 6y agoThe first version wasn't even a box - a paperback book with floppy disks. Imagine that - printed documentation!
- ygra 6y agoMy first foray into programming was reading the GW BASIC manual and then asking my father whether he could get me GW BASIC; I got QBasic instead, which nicely integrated all the text from that tome in the IDE. Right now I wonder what children will start with and how it would compare to my journey. Personally I feel, while JS in a browser is so much more capable, it's all but beginner-friendly and its main benefit to beginners is just ubiquity.
- userbinator 6y agoA more detailed answer (but still somewhat vague) for those wondering things like "how long are the lines" and "on what hardware" can be found in the linked thread: "110 cycles per source byte". Of course, that can vary significantly based on what those bytes actually represent (e.g. scanning through comments should take far fewer cycles than parsing keywords, numerical constants, or other expressions) so the actual "texture" of code being compiled will make a difference. ...and as someone who has spent a lot of time decompiling binaries, the lack of (any!) optimisations Delphi has reflects itself in the code it generates: It's extremely fast because it generates code extremely stupidly. Redundant moves, duplicated instructions(!), and other perplexingly stupid things are frequently seen. I suppose some of that might be a reflection of the quality of the source it was compiled from, but normally those don't show through with C compilers even at O0.
- deleted 6y ago[deleted]
- bjoli 6y agoI wrote a comment about a week ago in this very forum that a non-optimizing compiler should be able to compile about 1MLOC/s [0]. That seems to stay reasonably true a week later. What is more interesting is what tradeoffs you make to produce fast code. Chez scheme produces code that is plenty fast compared to most other scheme compilers, and does so at almost 100KLOC/s on my computer (on generated code that is relatively simple and already macro-expanded). They have strict limits on the time complexity on optimization passes, and even though some people have whined about it it seems to have served chez scheme well. [0]: https://news.ycombinator.com/item?id=24660468 https://news.ycombinator.com/item?id=24660468
- boznz 6y agoDelphi programs are still mainly compiled for windows desktops, I have noticed the binary for the 120K line MPR system I developed for my client has creeped up from about 8MB to 20MB since 2007. My current delphi 10.2 takes 7.2 seconds to do a full compile or about 2 seconds if I just hit the run button and it only has to re-compile the modules I was working on, this has remained pretty consistent over the 13 years since I first wrote it, despite improvements to the hardware. I think people can read too much in to your statement about the stupid source code the compiler generates (which I cannot confirm or deny), as the final exe binary is lightning fast without any optimisations, all performance issues I have ever encountered in Delphi go back to network calls such as REST APIs, MySQL libraries, printing, network drives, etc, good multi-threading can hide most. There are optimisation levels on Delphi but in 20 years I have never felt the need to go off the default. As a developer, I will take near instant compilation over optimisation any day.
- rudedogg 6y agoTweet text for the Twitter haters: > I wrote a synthetic program generator that can target different languages so I can get measurements across a bunch of different languages and compilers while varying the generator parameters. So far the champ among modern compilers is TCC and Delphi among historical compilers. > Even when running under a Windows 98 VM, Delphi 2 can compile large .pas files at 1.2 million lines per second. TCC comes in at 0.7 million lines per second. This is on a 2.5 GHz Skylake laptop. > All the modern Pascal compilers I could find did very poorly on the same benchmark workloads. Lazarus/FreePascal at 55 kloc/sec, Embarcadero Delphi at 15 kloc/sec. So 1.2 million lines/sec, running through a VM, on laptop hardware.
- pwdisswordfish4 6y agoNot surprising that TCC is slower; Pascal is much easier to parse then C.
- FullyFunctional 6y agoMore to the point, Wirth _designed_ Pascal to be one-pass translatable. Anders Hejlsberg took advantage of this in his succession of Pascal compilers: BLS Pascal (= Nascom Pascal), Compas Pascal, and Turbo Pascal. (Delphi is an evolution of Turbo Pascal but I don't know if he was involved).
- wenc 6y agoAnders Hejlsberg was the chief architect for Delphi at Borland, and at Microsoft he was lead architect for C# and Typescript.
- john_moscow 6y agoIf you want to be able to compile a certain language fast, translation units need to be modular. I.e. if Source1 is referenced by Source2 and Source3, you should be able to compile Source1 once, save its public part into a binary structure with logarithmic access time, and then just load it when compiling Source2 and Source3. This works splendidly with Pascal because each .pas file is split into interface and implementation sections. The interface section is a contextless description of what the module exports, that can be easily translated to a bunch of hash tables for functions, types, etc, that will be blazingly fast. It's a whole different story with C/C++. In order to support preprocessor macros and C++ templates, referencing a module means recursively "including" a bunch of header files (i.e. reparsing them from scratch), meaning O(n^2) complexity where n is the number of modules. You can speed it up with precompiled headers, but you will still need to separately parse each sequence of references (e.g. #include <Module1.h> \n #include <Module2.h> and #include <Module2.h> \n #include <Module1.h> will need to be precompiled separately. C++20 modules do address this, but since C/C++ is all about backwards compatibility, it's still a hot mess in real-world projects. That said, C# solves this problem near perfectly. Each .cs file can be easily translated to an mergeable and order-independent "public" part (i.e. hierarchical hash table of public types), and that part can be reused when building anything that references this file. It is also interesting how C# designers achieved most of the usability of C++ templates by using constrained generic types that are actually expanded at runtime (JIT IL-to-native translation to be more specific).
- Galanwe 6y ago> In order to support preprocessor macros and C++ templates, referencing a module means recursively "including" a bunch of header files (i.e. reparsing them from scratch), meaning O(n^2) complexity where n is the number of modules. You can speed it up with precompiled headers, but you will still need to separately parse each sequence of references Not sure I really get your point here. Even if you remove macros and templates, reading headers is actually necessary just for the sake of knowing the size of structures, the offsets of attributes, etc. How can _any_ language compile a unit passing a struct Foo on the stack without knowing the size of Foo (and thus having to read, say, foo.h)? Now I agree that if you play with preprocessor to have conditional things in your headers, reparsing will be necessary, but I guess this has been solved by include guards/pragma once a long time ago. 99% of preprocessor usage is project wide configuration, so wrapping the whole headers is fine. Not saying this is the best solution, but in practice, that shouldn't make much difference. A subtle distinction that can make quite a difference though is to provide independent forward declarations. A lot of times, your compiler will just need to know the symbols and signatures (e.g. When passing by reference), and providing the full structure definition is overkill and slower. I don't see enough people taking care to that, which is a pity
- bluedino 6y agoTurbo Pascal compiled thousands of lines a second on a 286. When I moved to Turbo C I was shocked at how long it took to compile code. What took 3 seconds now took 15.
- piinbinary 6y agoIf that scaled completely linearly - I'm sure it doesn't, but it might be close enough - it would mean that it could compile a few kloc in less time than most interpreters/VMs take to boot up. For me, "instant" compiler and test feedback would be the ideal development experience. (Plus a good debugger) I think sadly there are some features (e.g. HM-style type inference) that I want to have but would be an order of magnitude or two slower than this. But still, I'd love to see a compiler for a modern language use something like this as a goal. Even 10kloc/thread*sec would be quite good, now that we have 16+ thread CPUs readily available.
- 082349872349872 6y agoBack in the days of floppy drives, an interesting technical challenge was: write a system that boots, compiles itself, and enters its REPL before the drive mechanics manage to hit full RPM. What would the equivalent be on current systems? I suppose it might be possible to write a system that boots in a single bandwidth-delay product, but somehow that doesn't have the same attraction. ando wok fash nawit towsh nagut (running light without overbyte)
- willcipriano 6y agoBefore the flash drive heat throttles itself?
- e12e 6y agoThe "other" fast compiler (tcc) can do this: https://bellard.org/tcc/tcc-doc.html https://bellard.org/tcc/tcc-doc.html > TCC can be invoked from scripts, just as shell scripts. You just need to add #!/usr/local/bin/tcc -run at the start of your C source: #!/usr/local/bin/tcc -run #include <stdio.h> int main() { printf("Hello World\n"); return 0; } And famously, with some patches it can compile the Linux kernel at boot time (in reasonable time): https://bellard.org/tcc/tccboot.html https://bellard.org/tcc/tccboot.html
- psykotic 6y agoI'm the author of the tweet. Here's some more context: The main purpose of the testing was to measure compile time scaling on simple code that has straightforward equivalents in all languages. This meant integer and float operations, compound expressions making use of the full range of arithmetic and bitwise operators, local variables, function definitions and calls. So the code wasn't trivial (unlike most of the marketing-oriented tests or benchmarks I came across), but I also wasn't claiming that this was directly representative of a real-world code base of comparable size. I was working on a fast compiler (which generated machine code somewhere between gcc -O0 and -O1 in code quality) and wanted to have something to compare it across languages and compilers while being able to easily vary test parameters like total code size, size of each module, complexity of the module graph, identifier/whitespace/comment length distribution, etc. "Lines of code" is a pretty poor metric for engineering but unlike "tokens of code" or "bytes of code" it's something for which programmers have an intuitive sense of scale, so it made more sense for a tweet. Tokens of code is the most useful code size parameter for measuring one-pass compiler performance if you have to pick a single number. In an expression like "x + 1" you can assign the cost of the parsing, type checking and code generation of the expression (separate from the sub-expressions "x" and "1") to the "+" token. Even the cost of lexing is often dominated by the per-token cost (the switch jump on the leading byte is usually a forced branch mispredict of ~15 cycles) if you do the per-byte handling for variable-length tokens like identifiers efficiently. [1] If you fix the token distribution, you get almost-linear scaling with token count. [2] [1] Identifier bytes make up 60-70% of a typical code base, so micro-optimization can really pay off here if the rest of the compiler is fast. I used a SIMD method with a mispredict-free fast path for identifiers shorter than 16/32 bytes, with vectorized scanning and hashing, and the symbol table lookup/insertion was done at the same time and tuned such that it was mispredict-free 90% of the time for lookups and only had 1 mispredict for inserts which occur the first time a given identifier is seen in a module. [2] Except for threshold effects when your working set starts pushing you out of a level of the cache hierarchy. There's two factors: the size of your symbol working set, and your utilization of symbol hash tables. E.g. if a region of code is using a tiny subset of a huge symbol table, each loaded cacheline from the hash table is only expected to contain one symbol from your working set due to the pseudo-random distribution of hashes, but that caps out pretty quickly. With 64-byte cachelines and interleaved key/value pairs of 16 bytes, this part can't get worse than 25% cache utilization. So the worst-case footprint from the symbol working set is one 64-byte cacheline per symbol in the working set plus whatever associated symbol data is accessed. This utilization is improved if you put more symbol data directly into the hash table cacheline but unfortunately that would mean you don't have stable pointers to that data when you need to rehash.
- josephg 6y agoStats like this remind me how insanely slow the rust compiler is. Its possible to write a compiler which spends 110 cycles per source byte. How many cycles per source byte does the rust compiler consume? It seems like its 4-5 orders of magnitude slower - which is so crazy! Why is it so hard to optimize? Are we just being lazy? Whats going on?
- coldtea 6y ago>Are we just being lazy? "We" being who here? I'm pretty sure the Rust devs work like crazy on the language and its features -- they're not being "lazy". At best, they deprioritize compiler speed work, which is not the same as laziness.
- manfredo 6y agoPerhaps a better question is, what are compiler authors optimizing for? A compiler that runs in 3 seconds that produces code that's half the speed as a compiler that runs in 3 minutes is a worse option than the latter in plenty of use cases. And if we really care about minimizing compile times (and if we're being a little pedantic) we can just use an interpreted language and achieve zero compile times, by virtue of not doing any compiling at all. Rust and Pascal have different use cases in mind. I think a better question would be what are the different design philosophies between the two languages, and how this impacts compiler implementations.
- samatman 6y agoThere is an amount of time spent compiling which has a qualitative effect on my programming. I start to feel it around ten seconds, definitely by thirty; three minutes is way over the line. I start to be reluctant to make small tweaks. I want to program in 'blocks', time compiling with bathroom breaks. My frame is just wrecked, and I'm fairly convinced that code quality suffers from this. I like what Zig is doing, by taking such care to keep unoptimized builds as fast as possible. Release builds can run overnight for all I care, I'm fine with taking arbitrary amounts of time to get the fastest end product I can have. But I firmly believe that a language which can't give me a build in a handful of seconds is missing out, and it's a real pity Rust is in that category. It's possible that a language with type inference and a borrow checker simply must have slow compile times, that it's inherent. I doubt that somehow, though I concede that one-pass compiling a la Turbo Pascal is likely impossible.
- utopcell 6y agoI have fond memories of working in Turbo Pascal. Compiling and running a program felt instantaneous.
- 7kmph 6y agoSo what? compiler should catch bugs as soon as possible, as much as possible, at compile time, if it can do this fast, great! if not, then not that great, but far better than chewing through billions lines of code and do nothing, leaving you all your bugs to the run time.
- cable2600 6y agoThere used to be a Borland Museum that had free copies of Turbo Pascal and Turbo C, but it is down now as every link I have for it doesn't work. I was hoping they'd release Delphi 2.0 or 1.0 because it is 16 bit Windows.
- psykotic 6y agoDelphi 2 was the version that introduced the 32-bit compiler and ran on Windows 95. My impression is that Embarcadero (who bought and own the rights to Delphi) still have customers with legacy Delphi applications who pay them for their newer backward-compatible Delphi product, so they're unlikely to release the older versions for free. It's also a bit of a hassle to run on modern PCs. With Turbo Pascal you can just use DOSBox but you need to run Delphi on an old Windows version. If it runs in Wine, that might be the easiest option.
- phonon 6y agohttps://archive.org/details/DelphiDeveloper2 https://archive.org/details/DelphiDeveloper2
- cable2600 6y agoThanks
- marcocantu 6y agoThe old museum site is currently offline, but if you visit the Delphi 25th anniversary site (https://delphi.embarcadero.com/ https://delphi.embarcadero.com/) you can find in the menu at the top a link to download "Historic Delphi 1 Client/Server Install ISO"
- TheJimMcKeeth 6y agoMaybe we need to make a museum site museum.
- cable2600 6y ago
- stevefan1999 6y agoIt doesn't matter. Most of the time now is spent on code optimization. And it's becoming more significant everyday
- pjmlp 6y agoAnd me having a Gtk-rs project that takes 18 minutes to compile from scratch with an empty frame and a couple of menu entries on a Core Duo. My test project to validate compile time improvements on each Rust release. The C++ original with Gtkmm takes less than 10 minutes. Really miss Delphi like compile times, so then I just end up doing something on Qt, Lazarus or Eiffel Community instead.
- DonHopkins 6y agoReminds me of a comic I saw in an old Apple ][ magazine: (One kid talking to another, with dad in the background hunched over an Apple ][.) "Daddy's playing Pascal. That's where you try and see how many dots you can get before it beeps and you say nasty words."
- ykevinator 6y agoI used Delphi in the 90s. I am amazed it's still around.
- codeulike 6y agoIt was Delphi's 25th anniversary in February, here are a few articles https://www.theregister.com/2020/02/14/25_years_delphi_programming/ https://www.theregister.com/2020/02/14/25_years_delphi_progr... https://delphi.embarcadero.com/delphi-infoworld-vb-killer/ https://delphi.embarcadero.com/delphi-infoworld-vb-killer/
- pkphilip 6y agoFree Pascal and Lazarus - the open source alternative to Delphi, is also extremely fast. A demo that I put up sometime ago of developing a very simple GUI Hello World app from starting a fresh project to running it in less than 42 seconds. https://www.youtube.com/watch?v=XsCDqzL3k7k https://www.youtube.com/watch?v=XsCDqzL3k7k
- Havoc 6y agoYup. Delphi was always stupidly fast. I recall first time using another IDE I thought the compiler had hung. Nope...just slow.