A technique of lexer optimization was mentioned in two books: Engineering a compiler by K.Cooper et al. and Crafting a Compiler by C.Fischer et al. Here is the except from the first book (page 69):
While character-by-character I/O leads to clean algorithmic formulations, the overhead of a procedure call per character is significant relative to the cost of simulating the DFA in either a table-driven or a direct-coded scanner. To reduce the I/O cost per character, the compiler writer can use buffered I/O, where each read operation returns a longer string of characters, or buffer, and the scanner then indexes through the buffer. The scanner maintains a pointer into the buffer...
My question is, what is the significance of this technique? Now that memory buffering is often already implemented by the Operating System, why did the authors suggest we implement a buffer? (Also, standard libraries provided by high-level languages usually have a buffer maintained with the filestream handling routines, like C++'s std::ifstream).
I know in some applications, like database systems, a custom buffer mechanism is not only desirable (knows more about access patterns), but sometimes necessary (recovery, logging). Do similar reasongs apply to lexers in compilers? If so, how?
EDIT: Here is a similar question: link, but I'd like to know more about the arguments for a custom buffer (like the argument supporting a buffer in database systems), if there is any.
Another post here compared manual buffering with std::fstream buffering in C++.