They can be fast (see for example the Rust parser-combinator library Nom [0] which benchmarks competitively with hand-written parsers). However you likely need some level of metaprogramming to make them fast, as the way they're implemented in, say, Haskell has a lot of function call overhead that's hard to optimize. Nom uses macros, and the generated code tends to look a lot like the sort of state machine you'd write by hand.
That said, the main benefit of parser combinators for me are that they're super easy and fast to write, and easy to modify. So I tend to use a PC library for prototyping, then if I need more performance I'll rewrite it by hand.
> ...as the way they're implemented in, say, Haskell has a lot of function call overhead that's hard to optimize.
GHC inlines aggressively (when you use -O) so there shouldn't be much function call overhead. As others have commented, the bigger issue is that monadic parsers are generally unable to perform static analysis of the full parse tree and thus identify the aspects which parallel branches have in common, which implies more backtracking and redundant parsing. Some of this can be improved heuristically with rewrite rules, or by explicitly using applicative combinators (which can be statically analyzed) instead of monadic ones.
That said, the main benefit of parser combinators for me are that they're super easy and fast to write, and easy to modify. So I tend to use a PC library for prototyping, then if I need more performance I'll rewrite it by hand.
[0] https://github.com/Geal/nom