词法分析器中的文件缓冲:现在 OS(和语言库)已经在内部实现了缓冲区,这是否可取?
File buffering in lexers: is it advisable, now that the OS (and language libraries) already implement buffers internally?
两本书中提到了词法分析器优化技术:Engineering a compiler by K.Cooper et al。以及 C.Fischer 等人制作的编译器。这是第一本书(第 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...
我的问题是,这种技术的意义是什么?既然内存缓冲通常已经由操作系统实现,为什么作者建议我们实现一个缓冲区? (此外,高级语言提供的标准库通常有一个由文件流处理例程维护的缓冲区,如 C++ 的 std::ifstream)。
我知道在某些应用程序中,如数据库系统,自定义缓冲区机制不仅是可取的(对访问模式了解更多),而且有时是必要的(恢复、日志记录)。类似的原因是否适用于编译器中的词法分析器?如果可以,怎么做?
编辑:
这是一个类似的问题:,但我想知道更多关于自定义缓冲区的参数(如支持数据库系统中缓冲区的参数),如果有的话。
另一个 post here 将手动缓冲与 C++ 中的 std::fstream 缓冲进行了比较。
正如其他人所指出的,无论 OS 缓冲区是否存在(确实存在),您的应用程序依赖它的成本都非常高,因为那些 OS/File 系统缓冲区不在您的应用程序中地址 space。为什么?因为您的应用要获取该数据,通常需要通过调用层才能到达 OS 缓冲区。如果您一次为 1 character/byte 执行此操作,则会产生开销。
如果您使用的是 IO 库:出于性能原因,它们中的一些会读取或将读取 'ahead',并将 OS 调用保持在最低限度。
另一方面,如果您在没有利用库的情况下进行操作,那么强烈建议您设置缓冲 IO 功能,原因与其他库相同。
最后,你编译的最终结果是一个可执行的东西。除非您不允许 IO 发生,否则出于同样的原因,您将希望有特定于您的语言(假设自托管)运行-time 来提供缓冲 IO。如果您的 运行-time 是基于提供它的语言或一系列库,那么您应该很好。
Do similar reasons apply to lexers in compilers?
有时,当然。例如,考虑 returns 表示 "this is a variable name" 的词法分析器规则。解析器不仅需要 "is a variable name" 标记本身,还需要实际名称:在不知道名称是 Fred、Wilma、Barney 还是其他任何名称的情况下知道这是一个名称是没有用的。
如果是一个名字,那么名字应该存储在哪里呢?您能否授予解析器直接访问保存名称本身的字节流的权限? (如果是,需要多长时间?解析器需要多长时间?)
或者考虑一个字符串文字(无论它们有什么语法)。组成字符串的字符存储在哪里?您可以直接授予对原始缓冲区的访问权限吗?
如果您拥有提供这些扫描时间缓冲区的数据结构,您可以可以授予对它们的有限访问权限,并且知道借用字符串的确切生命周期可能是什么.根据更多细节,这可能会让您避免制作副本(至少有时是这样)。如果您正在使用某些库提供的缓冲 I/O 例程,这些例程承诺一次只传送一个字符,您绝对 不能 授予此类访问权限。
两本书中提到了词法分析器优化技术:Engineering a compiler by K.Cooper et al。以及 C.Fischer 等人制作的编译器。这是第一本书(第 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...
我的问题是,这种技术的意义是什么?既然内存缓冲通常已经由操作系统实现,为什么作者建议我们实现一个缓冲区? (此外,高级语言提供的标准库通常有一个由文件流处理例程维护的缓冲区,如 C++ 的 std::ifstream)。
我知道在某些应用程序中,如数据库系统,自定义缓冲区机制不仅是可取的(对访问模式了解更多),而且有时是必要的(恢复、日志记录)。类似的原因是否适用于编译器中的词法分析器?如果可以,怎么做?
编辑:
这是一个类似的问题:
另一个 post here 将手动缓冲与 C++ 中的 std::fstream 缓冲进行了比较。
正如其他人所指出的,无论 OS 缓冲区是否存在(确实存在),您的应用程序依赖它的成本都非常高,因为那些 OS/File 系统缓冲区不在您的应用程序中地址 space。为什么?因为您的应用要获取该数据,通常需要通过调用层才能到达 OS 缓冲区。如果您一次为 1 character/byte 执行此操作,则会产生开销。
如果您使用的是 IO 库:出于性能原因,它们中的一些会读取或将读取 'ahead',并将 OS 调用保持在最低限度。
另一方面,如果您在没有利用库的情况下进行操作,那么强烈建议您设置缓冲 IO 功能,原因与其他库相同。
最后,你编译的最终结果是一个可执行的东西。除非您不允许 IO 发生,否则出于同样的原因,您将希望有特定于您的语言(假设自托管)运行-time 来提供缓冲 IO。如果您的 运行-time 是基于提供它的语言或一系列库,那么您应该很好。
Do similar reasons apply to lexers in compilers?
有时,当然。例如,考虑 returns 表示 "this is a variable name" 的词法分析器规则。解析器不仅需要 "is a variable name" 标记本身,还需要实际名称:在不知道名称是 Fred、Wilma、Barney 还是其他任何名称的情况下知道这是一个名称是没有用的。
如果是一个名字,那么名字应该存储在哪里呢?您能否授予解析器直接访问保存名称本身的字节流的权限? (如果是,需要多长时间?解析器需要多长时间?)
或者考虑一个字符串文字(无论它们有什么语法)。组成字符串的字符存储在哪里?您可以直接授予对原始缓冲区的访问权限吗?
如果您拥有提供这些扫描时间缓冲区的数据结构,您可以可以授予对它们的有限访问权限,并且知道借用字符串的确切生命周期可能是什么.根据更多细节,这可能会让您避免制作副本(至少有时是这样)。如果您正在使用某些库提供的缓冲 I/O 例程,这些例程承诺一次只传送一个字符,您绝对 不能 授予此类访问权限。