News for hackers. Stuff that matters.
Re:My Most Important Project Was a Bytecode Interpreter by robertelder on Wednesday September 21, 2016 @10:46PM (#12553967)
One of the moments where I really started to feel like I was starting to 'see the matrix' was when I was working on a regex engine to try to make my compiler faster (it didn't, but that's another story). The asymptotically fast way to approach regex processing actually involves writing a parser to process the regex, so in order to write a fast compiler, you need to write another fast compiler to process the regexes that will process the actual programs that you write. But, if your regexes get complex, you should really write a parser to parse the regexes that will parse the actual program. This is where you realize that it's parsers all the way down.

When you think more about regexes this way, you realize that a regex is just a tiny description of a virtual machine (or emulator) that can process the simplest of instructions (check for 'a', accept '0-9', etc.). Each step in the regex is just a piece of bytecode that can execute, and if you turn a regex on its side you can visualize it as just a simple assembly program.

Re:My Most Important Project Was a Bytecode Interpreter by wyager on Wednesday September 21, 2016 @11:53PM (#12554201)
I mean, the whole point of regexes (not to be confused with PCREs) is that any given regex is isomorphic to some canonical finite state machine. It is, specifically speaking, a tiny description of an FSM over the alphabet of ASCII characters (or whatever charset you're using).

Interestingly, regexes/FSMs are (IIRC) the most powerful class of machines for which equivalence is decidable. So if you give me any two regexes, I can tell you if they match on all the same strings, but this is not true for any more powerful grammar.

Re:My Most Important Project Was a Bytecode Interpreter by halter73 on Thursday September 22, 2016 @03:19AM (#12555078)
Isn't it possible to decide the equivalence of deterministic pushdown automata? Wouldn't DPDAs be considered more powerful than FSMs due to the addition of a stack?

Wikipedia [1] shows there's a paper called "The equivalence problem for deterministic pushdown automata is decidable" that won the Gödel Prize is 2002. I haven't read the paper nor do I currently have access to it though.

[1] https://en.wikipedia.org/wiki/Deterministic_pushdown_automat...

Re:My Most Important Project Was a Bytecode Interpreter by kefka on Thursday September 22, 2016 @07:18AM (#12556004)
Here you go!

http://link.springer.com.sci-hub.cc/chapter/10.1007/3-540-63...

It was initially published in 1997.

Re:My Most Important Project Was a Bytecode Interpreter by wyager on Thursday September 22, 2016 @11:06AM (#12557293)
Huh! Well there you go.
Re:My Most Important Project Was a Bytecode Interpreter by adrianratnapala on Thursday September 22, 2016 @01:24AM (#12554575)
Presumably that means "this is not true for any more powerful class of grammars".

Any particular pair grammars from that class. I mean if you showed me a yacc grammar for Pascal and another one for Java, I am sure I could prove they were ineqivelent.

More tricky, if you gave someone clever a hand written Pascal parser and that same yacc grammar she could probably prove equivilency with some effort. But there is no guarantee that this is always possible.

Re:My Most Important Project Was a Bytecode Interpreter by wyager on Thursday September 22, 2016 @01:50AM (#12554697)
Yes, that is what I meant.

> I mean if you showed me a yacc grammar for Pascal and another one for Java,

This is why I said "any", and not "all". In most practical cases, you can tell if two grammars are different, but it's easy to construct cases where you can't.

Re:My Most Important Project Was a Bytecode Interpreter by hvidgaard on Thursday September 22, 2016 @02:17AM (#12554811)
While it is true for Regular Languages (FSM) strict RegExs, it's hardly true for any contemporary implementation of RegExs. They have back references and other constructs that make them more powerful than a Regular Language, and thereby make it impossible to decide equivalence in the general case.
Re:My Most Important Project Was a Bytecode Interpreter by wyager on Thursday September 22, 2016 @02:55AM (#12554986)
Hence "not to be confused with PCREs", which most pseudo-regex implementations are based off of.
Re:My Most Important Project Was a Bytecode Interpreter by Hydraulix989 on Thursday September 22, 2016 @03:12AM (#12555052)
I'll ask the "dumb question" then: What is a PCRE? How is it different than a "true" regex?
Re:My Most Important Project Was a Bytecode Interpreter by robewald on Thursday September 22, 2016 @03:26AM (#12555107)
PCREs are Perl Compatible Regular Expressions, they have backreferences and other constructs. Almost all languages that have Regular Expressions have similar constructs. "Computer Science" Regular Expressions are more limited and implement a "regular language" as defined in https://en.wikipedia.org/wiki/Chomsky_hierarchy. This gives some guarantees, which go out the window with PCREs.
Re:My Most Important Project Was a Bytecode Interpreter by hvidgaard on Thursday September 22, 2016 @10:00AM (#12556840)
Did you edit the comment? I cannot recall reading that at all, but I may have been in a hurry.
Re:My Most Important Project Was a Bytecode Interpreter by wyager on Thursday September 22, 2016 @01:34PM (#12558563)
Nope, didn't change it!
Re:My Most Important Project Was a Bytecode Interpreter by signa11 on Thursday September 22, 2016 @02:21AM (#12554832)
> When you think more about regexes this way, you realize that a regex is just a tiny description of a virtual machine (or emulator) that can process the simplest of instructions (check for 'a', accept '0-9', etc.). Each step in the regex is just a piece of bytecode that can execute, and if you turn a regex on its side you can visualize it as just a simple assembly program.

which is _exactly_ what bpf does :)

Re:My Most Important Project Was a Bytecode Interpreter by posterboy on Thursday September 22, 2016 @11:13AM (#12557351)
A regular expression is by definition a regular grammar, the least mighty language in the chomsky hierarchy and realizable by finite state automaton.

You can get something similar to a virtual equivalent of a turing complete language, due to the fact that the tape of the turing machine is, contrary to the hypothetical theory, practically limit by recourses. CPUs are finite state automatons, yet we use them to solve problems of sufficiently low complexity in NP space.

I am not an expert, please correct me if I am wrong.

Re:My Most Important Project Was a Bytecode Interpreter by pmiller2 on Thursday September 22, 2016 @03:05PM (#12559317)
Real computers are much closer to linear bounded automata than full Turing machines.

https://en.m.wikipedia.org/wiki/Linear_bounded_automaton

Re:My Most Important Project Was a Bytecode Interpreter by chrisseaton on Wednesday September 21, 2016 @10:56PM (#12553996)
I don't get it - what do regexps have to do with compilers and how do they make compilers faster?
Re:My Most Important Project Was a Bytecode Interpreter by ender7 on Wednesday September 21, 2016 @11:09PM (#12554043)
The first step in compilation is lexing -- converting a character stream to a stream of semantic "tokens", where a token might be "a number literal" or "the 'while' keyword" or a single character token like "{". This process is usually done via regexs.
Re:My Most Important Project Was a Bytecode Interpreter by vidarh on Thursday September 22, 2016 @05:50AM (#12555698)
It is rare for lexers to use actual regex engines, in my experience, as it's impractical if you want to do proper error reporting unless you write your own regex engine in which case people tend to opt for hand-writing lexer rules.

It's not unheard of, and I have the impression it's getting more common, but still only a small proportion of the compilers I've seen over the years explicitly use regexps.

Re:My Most Important Project Was a Bytecode Interpreter by rocket69 on Thursday September 22, 2016 @06:46AM (#12555885)
So, what parses the regex in the lex, flex, Jison, etc...
Re:My Most Important Project Was a Bytecode Interpreter by vidarh on Thursday September 22, 2016 @06:55AM (#12555913)
Most tools like that reduces any regexes to dfa's or similar, but most production compilers I've seen don't use tools like that because they're a pain to do proper error reporting for.
Re:My Most Important Project Was a Bytecode Interpreter by rocket69 on Thursday September 22, 2016 @03:38PM (#12559661)
Yea, we're not talking about compilers, we're talking about lexers. Regex doesn't even make a little bit of sense in a compiler world. What lexer are you working with?
Re:My Most Important Project Was a Bytecode Interpreter by vidarh on Friday September 23, 2016 @07:35AM (#12563788)
One of the main uses of lexers are in compiler.

There are others, certainly, like parsing various configuration formats etc. but they tend to either use tool generated lexers that tend to use dfa's, or handwritten lexers that may or may not use regexes, but there too it's fairly uncommon to see much regex use.

I custom write all of my lexers for exactly the reasons I outlined above.

Re:My Most Important Project Was a Bytecode Interpreter by chrisseaton on Wednesday September 21, 2016 @11:37PM (#12554137)
I didn't think of lexer rules as regular expressions but I suppose they are of course.

But I can't imagine a lexer would ever be the performance bottleneck in a compiler.

Re:My Most Important Project Was a Bytecode Interpreter by adrianratnapala on Thursday September 22, 2016 @01:19AM (#12554552)
According to textbooks, lexers are the bottleneck because they are the only part that has to literally look at every byte of the source (I am including hashing as part of the lexing process).

I am not sure if this is true any more. It probably depends on the language.

Even as CPUs grow faster, code bases grow bigger, so the number-of-bytes argument is still important. On the other hand, heavy optimisations and difficult languages like C++ will shift the bottlenecks to later stages.

Re:My Most Important Project Was a Bytecode Interpreter by readittwice on Thursday September 22, 2016 @03:47AM (#12555213)
I think I read that too, but I am not sure that this is actually true. Please correct me if I am wrong, according to the Rust developers code generation seems to be the bottleneck. That's why they are working on incremental compilation to improve compilation times. They detect changes in the input files by comparing the AST to the old version. So parsing is always necessary but later stages can be cached. That seems to confirm that parsing is not the bottleneck, at least not for Rust.

OTOH that probably also depends on your use case, JS for example needs to get parsed at every page load. Some JS-VMs only parse the source code lazily, at first the parser only detects function boundaries. Only if this function is really executed, the function gets parsed completely.

Re:My Most Important Project Was a Bytecode Interpreter by dan00 on Thursday September 22, 2016 @05:02AM (#12555523)
> I think I read that too, but I am not sure that this is actually true. Please correct me if I am wrong, according to the Rust developers code generation seems to be the bottleneck.

You're both right. The problem of C++ is how '#include' works, that it just includes the content of all files and therefore there's more overhead on the lexing side.

Rust's "equivalent" of '#include' is 'use', which doesn't have this problem, because it doesn't concatenates files.

Re:My Most Important Project Was a Bytecode Interpreter by barrkel on Thursday September 22, 2016 @05:46AM (#12555691)
You can make codegen faster by doing less work and producing less sophisticated code. You can't not look at every byte. It's the limiting factor in fastest possible compilation, not what takes the most time in most production compilers.
Re:My Most Important Project Was a Bytecode Interpreter by Gibbon1 on Thursday September 22, 2016 @06:36AM (#12555846)
I suspect that modern languages try and fix some of this by making the syntax unambiguous. Means you only need to tokenize each file exactly once. Compare with older languages where if you change a header/module/etc you need to reparse the whole shebang.

Possible with rust that moves a bunch of the grant work into the code generator. AKA where as in C/C++ by the time you're generating code all your type information is set in stone, possible in rust a bunch of stuff isn't resolved yet.

Re:My Most Important Project Was a Bytecode Interpreter by adrianratnapala on Thursday September 22, 2016 @06:20AM (#12555788)
Rust uses LLVM, a heavyweight backend with fearsomely thorough optimisation.

It might be that for non-optimised output, the parser becomes the bottleneck again. Or it might be that LLVM just imposes overhead even for the unoptimised case, that pays for itself in the optimised case.

Re:My Most Important Project Was a Bytecode Interpreter by titzer on Thursday September 22, 2016 @06:31AM (#12555824)
Depending on how source programs are split up into files, parsing can be easily parallelized (think one thread per file), while other compilation tasks are harder due to interdependencies. E.g. semantic analysis requires building type representations, global namespaces, etc. Code generation is (usually) parallelizable as well, but there are a couple very serial steps in the middle, too.

My experience is that parsers for source languages can reach into the 1-10mb/s range, and depending on how complex the IRs and transformations are after that, code generation is usually around 0.5mb-5mb/s. The stuff in the middle (dealing with IRs) is harder to measure in terms of bytes.

Re:My Most Important Project Was a Bytecode Interpreter by ab129c871xy on Thursday September 22, 2016 @05:16AM (#12555569)
Perhaps in an ancient one-pass C compiler. Modern compilers build many trees, usually one for each pass. Later stages do expensive operations on sets (even without optimization one has to do basic register allocation), so I'd say the lexing stage is entirely negligible.
Re:My Most Important Project Was a Bytecode Interpreter by jbangert on Thursday September 22, 2016 @03:32AM (#12555135)
C++ compilers (at least on most current code bases that don't need modules) still need to parse and lex headers though -- so actual executable code is pretty rare. Most compilations are also debug builds which don't optimize(but creating debug information can also be slow; the really slow step is usually linking)
Re:My Most Important Project Was a Bytecode Interpreter by signa11 on Thursday September 22, 2016 @04:20AM (#12555346)
> But I can't imagine a lexer would ever be the performance bottleneck in a compiler.

one rather trivial way to observe the effects of avoiding building a source file is to use ccache. ccache avoids the recompilation (even if you do a make clean, or some such), and it is not uncommon to observe speed ups of factor of 5 or so.

however, once you have crossed that barrier, you hit the linking wall. which is where you would end up spending a large portion of time. gold (https://en.wikipedia.org/wiki/Gold_(linker)) optimizes that i.e. supports incremental linking, but unfortunately, i haven't had any experience in large code-bases where it is being used.

Re:My Most Important Project Was a Bytecode Interpreter by pertymcpert on Thursday September 22, 2016 @06:17AM (#12555775)
No chance, modern compilers spend most of their time in the optimization stages. Lexing is peanuts.
Re:My Most Important Project Was a Bytecode Interpreter by signa11 on Thursday September 22, 2016 @06:40AM (#12555864)
Try it. You _might_ be surprised :)
Re:My Most Important Project Was a Bytecode Interpreter by kjax on Thursday September 22, 2016 @01:52AM (#12554710)
Lexer generators typically allow describing rules with regular expressions, but through Thompson's construction, subset construction, and DFA minimization, you can end up with a blazing fast/optimized DFA that processes your input at maximum speed.
Re:My Most Important Project Was a Bytecode Interpreter by paulddraper on Wednesday September 21, 2016 @11:51PM (#12554189)
I think they're usually done with a specific FSM, rather than general regular expressions.
Re:My Most Important Project Was a Bytecode Interpreter by titzer on Thursday September 22, 2016 @06:26AM (#12555804)
Not all parsers do a lexing step. Such ones are called "scannerless parsers" and can be much, much faster than parsers with a separate lexing step.
Re:My Most Important Project Was a Bytecode Interpreter by duaneb on Wednesday September 21, 2016 @11:16PM (#12554071)
A lot of optimizations on arbitrary byte code often look for patterns in byte streams (or in reified assembly) in similar ways to regexes.
Re:My Most Important Project Was a Bytecode Interpreter by teraflop on Wednesday September 21, 2016 @11:58PM (#12554224)
For many years, an important stage of the GHC Haskell compiler consisted of a giant Perl script full of regexes.

http://code.haskell.org/ghc-scp/ghc/docs/comm/the-beast/mang...

Re:My Most Important Project Was a Bytecode Interpreter by Lanzaa on Thursday September 22, 2016 @11:20AM (#12557417)
If you spent much time looking at regexs you might enjoy this set of articles about improving regex engine performance:

https://swtch.com/~rsc/regexp/regexp1.html