- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在代码中遇到一种情况,其中有一个巨大的功能,可以逐行解析记录,验证并写入另一个文件。
如果文件中有错误,它将调用另一个函数来拒绝记录并写入拒绝原因。
由于程序中的内存泄漏,它会随着SIGSEGV崩溃。一种从崩溃位置“重新启动”文件的解决方案是将最后处理的记录写入一个简单文件。
为此,需要将处理循环中的当前记录号写入文件。如何确保循环中的数据被覆盖?
使用fseek在循环中首先定位/倒带是否会降低性能?
记录的数量有时可能很多(最多500K)。
谢谢。
编辑:内存泄漏已得到修复。建议重新启动解决方案为
额外的安全措施和手段以及SKIP n记录解决方案提供重启机制。对不起,您之前没有提到它。
最佳答案
遇到此类问题时,可以采用以下两种方法之一:
建议的方法:对于每个读取的记录,将记录号(或输入文件中ftell
返回的位置)写到单独的书签文件中。为确保完全从上次中断的地方恢复,以免引入重复的记录,每次写入(对fflush
和输出/拒绝文件都必须)后必须bookmark
。通常,此操作和无缓冲的写入操作都会减慢速度典型(无故障)场景。为了完整起见,请注意您有三种写入书签文件的方式:fopen(..., 'w') / fwrite / fclose
-非常慢rewind / truncate / fwrite / fflush
-快一点rewind / fwrite / fflush
-更快一些;您可以跳过truncate
,因为记录号(或ftell
位置)将总是与上一个记录号(或ftell
位置)一样长或更长,并且将完全覆盖它,前提是您一次在以下位置截断了文件启动(这回答了您的原始问题)
假设在大多数情况下一切都会顺利;在故障后恢复时,只需计算已输出的记录数(正常输出加拒绝),然后从输入文件中跳过等效的记录数。
这样可以使典型的(无故障)场景保持极快的速度,而不会在出现故障后恢复的情况下大幅降低性能。
您不需要fflush
文件,或者至少不需要那么频繁。在切换到写入拒绝文件之前,您仍然需要fflush
主输出文件,而在切换回写入主输出文件之前,您仍然需要fflush
在拒绝文件中(对于500k记录,可能需要数百或数千次)只需从输出/拒绝文件中删除最后一个未终止的行,直到该行的所有内容都将保持一致。
我强烈建议使用方法2。与方法2所需的任何其他(缓冲的)读取(fflush
可能需要数毫秒;将其乘以500k并得到分钟数相比,方法1所引起的写入(三种可能性中的任一种)都非常昂贵) 500k记录文件中的行数仅需几秒钟,而且,文件系统缓存正在使用,而不是对此不利。)
编辑
只是想阐明实现方法2所需的确切步骤:
当分别写入输出和拒绝文件时,仅在从写入一个文件切换到写入另一个文件时才需要刷新。请考虑以下情形,以说明进行这些文件刷新的必要性:
假设您将1000条记录写入主输出文件,则
您必须向拒绝文件写入1行,而无需先手动刷新主输出文件,然后
您将200多行写入主输出文件,而无需先手动刷新拒绝文件,然后
运行时会自动为您刷新主输出文件,因为您已经在主输出文件的缓冲区中积累了大量数据,即1200条记录
但是运行时尚未为您自动将拒绝文件刷新到磁盘,因为文件缓冲区仅包含一条记录,该记录不足以自动刷新
您的程序在此时崩溃
您可以恢复并计数主输出文件中的1200条记录(运行时会为您清除这些记录),但是拒绝文件中的0(!)记录(未刷新)。
假设仅成功处理了1200条记录到主输出文件,则在记录#1201处继续处理输入文件;被拒绝的记录将丢失,并且第1200个有效记录将被重复
你不要这个!
现在考虑在切换输出/拒绝文件后手动刷新:
假设您将1000条记录写入主输出文件,则
您遇到一条无效记录,该记录属于拒绝文件;最后一条记录有效;这意味着您将切换到写入拒绝文件:在写入拒绝文件之前刷新主输出文件
您现在将1行写入拒绝文件,然后
您遇到一条属于主输出文件的有效记录;最后一条记录无效;这意味着您将切换到写入主输出文件:在写入主输出文件之前刷新拒绝文件
您将200多行写入主输出文件,而无需先手动刷新拒绝文件,然后
假设运行时没有为您自动刷新任何内容,因为自上次对主输出文件进行手动刷新以来,缓冲的200条记录不足以触发自动刷新
您的程序在此时崩溃
您可以在主输出文件中恢复并计数1000条有效记录(在切换到拒绝文件之前手动刷新了记录),在拒绝文件中记录了1条记录(在切换回主输出文件之前手动刷新了记录)。
您可以正确地恢复处理记录#1001处的输入文件,该记录是无效记录之后的第一个有效记录。
您会重新处理接下来的200条有效记录,因为它们没有被刷新,但是没有丢失的记录,也没有重复的记录
如果您对运行时的自动刷新之间的间隔不满意,也可以每100或每1000条记录进行一次手动刷新。这取决于处理记录是否比刷新更昂贵(如果处理更昂贵,则应在每个记录之后频繁刷新,否则仅当在输出/拒绝之间切换时才刷新)。
从失败中恢复
打开输出文件和拒绝文件以进行读取和写入,然后从读取和计数每个记录(例如records_resume_counter
)开始,直到到达文件末尾
除非您在输出每条记录后都进行刷新,否则还需要对输出和拒绝文件中的最后一条记录进行一些特殊处理:
从中断的输出/拒绝文件中读取记录之前,请记住您在该输出/拒绝文件中的位置(使用ftell
),我们将其称为last_valid_record_ends_here
阅读记录。验证该记录不是部分记录(即运行时尚未将文件刷新到记录的中间)。
如果每行有一条记录,可以通过检查记录中的最后一个字符是回车符还是换行符(\n
或`r`)轻松地进行验证
如果记录已完成,请增加记录计数器并继续下一条记录(或文件结尾,以先到者为准)。
如果记录是不完整的,则将fseek
返回到last_valid_record_ends_here
,并停止从此输出/拒绝文件读取;不要增加计数器;继续进行下一个输出或拒绝文件,除非您已遍历所有这些文件
打开输入文件进行读取,并从中跳过records_resume_counter
条记录
继续处理并输出到输出/拒绝文件;这将自动附加到输出/拒绝文件,您无需在其中读取/计数已处理的记录
如果必须对部分记录刷新执行特殊处理,则输出的下一条记录将覆盖上一次运行(在last_valid_record_ends_here
处)的部分信息-您将没有重复,垃圾或丢失的记录。
关于c - fseek/循环倒带,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/605247/
运行 PostgreSQL(7.4 和 8.x),我认为这是可行的,但现在我遇到了错误。 我可以单独运行查询,它工作得很好,但如果我使用 UNION 或 UNION ALL,它会抛出错误。 这个错误:
我试图为我的应用程序创建一个导航,使用抽屉导航我的 fragment 之一(HomeFragment)有一个 ViewPager,可容纳 3 个 fragment (Bundy Clock、Annou
以我目前正在开发的应用为例: - 它有一个包含多个项目的抽屉导航;现在有两个项目让我感兴趣,我将它们称为 X 和 Y。 X 和 Y 都在单击时显示包含 x 元素或 y 元素列表的 fragment 选
我有一个形状为 (370,275,210) 的 NumPy 数组,我想将其重新整形为 (275,210,370)。我将如何在 Python 中实现这一点? 370是波段数,275是行数,210是图像包
我们如何与被子 UIViewController 阻止的父 UIViewController(具有按钮)交互。显然,触摸事件不会通过子 Nib 。 (启用用户交互) 注意:我正在加载默认和自定义 NI
我是 Jpa 新手,我想执行过程 我的代码如下 private static final String PERSISTENCE_UNIT_NAME = "todos"; private static
与安装了 LAMP 的 GCE 相比,选择与 Google Cloud SQL 链接的 GCE 实例有哪些优势? 我确定 GCE 是可扩展的,但是安装在其上的 mysql 数据库的可扩展性如何? 使用
这个问题在这里已经有了答案: Value receiver vs. pointer receiver (3 个答案) 关闭 3 年前。 我刚接触 golang。只是想了解为 Calc 类型声明的两种
我不小心按了一个快捷键,一个非常漂亮的断线出现在日期上。 有点像 # 23 Jun 2010 -------------------- 有人知道有问题的快捷方式吗?? (我在 mac 上工作!) 在
我正在Scala中编写正则表达式 val regex = "^foo.*$".r 这很好,但是如果我想做 var x = "foo" val regex = s"""^$x.*$""".r 现在我们有
以下 XML 文档在技术上是否相同? James Dean 19 和: James Dean 19 最佳答案 这两个文档在语义上是相同的。在 X
我在对数据帧列表运行稳健的线性回归模型(使用 MASS 库中的 rlm)时遇到问题。 可重现的示例: var1 <- c(1:100) var2 <- var1*var1 df1 <- data.f
好的,我有一个自定义数字键盘,可以在标签(numberField)中将数字显示为 0.00,现在我需要它显示 $0.00。 NSString *digit = sender.currentTitle;
在基于文档的应用程序中,使用 XIB 文件,创建新窗口时其行为是: 根据最后一个事件的位置进行定位和调整大小 window 。 如果最后一个事件窗口仍然可见,则新窗口 窗口应该是级联的,这样它就不会直
我想使用参数进行查询,如下所示: SELECT * FROM MATABLE WHERE MT_ID IN (368134, 181956) 所以我考虑一下 SELECT * FROM MATABLE
我遇到一些性能问题。 我有一个大约有 200 万行的表。 CREATE TABLE [dbo].[M8]( [M8_ID] [int] IDENTITY(1,1) NOT NULL,
我在 jquery 中的按键功能遇到问题。我不知道为什么按键功能不起作用。我已经使用了正确的 key 代码。在我的函数中有 2 个代码,其中包含 2 个事件键,按一个键表示 (+) 代码 107 和(
我想显示音频波形,我得到了此代码,它需要.raw音频输入并显示音频波形,但是当我放入.3gp,.mp3音频时,我得到白噪声,有人可以帮助我如何使其按需与.3gp一起使用使用.3gp音频运行它。 Inp
我无法让 stristr 函数返回真值,我相信这是因为我的搜索中有一个 $ 字符。 当我这样做时: var_dump($nopricecart); 完整的 $nopricecart 值是 $0 ,我得
如果我有这样的循环: for(int i=0;i O(n) 次。所以do some执行了O(n)次。如果做某事是线性时间,那么代码片段的复杂度是O(n^2)。 关于algorithm - 带 If 语
我是一名优秀的程序员,十分优秀!