1

我有一个适用于 CSV 文件的摇摆应用程序。它逐行读取完整文件,计算一些所需的统计数据并显示输出。输出屏幕的上半部分按 J​​Table 中的顺序显示文件中的每条记录,而下半部分显示基于该数据计算的统计信息。问题是 JVM 占用的内存是文件大小的 4 倍。(在处理 86MB 的文件堆区域时使用 377 MB 的空间 - 使用 jVisualVM 检查内存利用率)。

笔记:

  1. 我使用 LineNumberReader 读取文件(由于特定要求,如果这有助于内存使用,我可以更改它)

  2. 为了读取每一行,使用 readLine(),然后为该记录的各个字段调用 String 的那一行的 .split(',')。

  3. 每条记录存储在 Vector 中,以便在 JTable 中显示,而其他统计信息存储在 JavaBean 类中的 HashMap、TreeMap 和摘要数据中。还使用 JFreeChart 绘制了一张图。

请建议减少内存利用率,因为我需要处理 2GB 文件。

4

4 回答 4

1

尝试给OpenCSV一个机会。它仅在您使用 readNext() 方法时存储最后读取的行。对于大文件,这是完美的。

在他们的网站上,以下是他们支持的功能:

  • 每行任意数量的值

  • 忽略引用元素中的逗号

  • 处理带有嵌入回车的引用条目(即跨越多行的条目)

  • 可配置的分隔符和引号字符(或使用合理的默认值)

  • 一次阅读所有条目,或使用迭代器样式模型

  • 从 String[] 创建 csv 文件(即嵌入引号字符的自动转义)

于 2012-04-24T17:51:17.877 回答
0

使用最佳实践来升级您的程序

  1. 在程序中编写多线程以获得更好的cpu利用率。
  2. 设置堆最小和最大堆大小以更好地使用 ram。
  3. 使用正确的数据结构和设计。
于 2012-04-24T17:43:54.793 回答
0

每个 Java 对象都有内存开销,所以如果你的字符串真的很短,这可以解释为什么你的文件大小是 4 倍。您还必须计算 Vector 的大小及其内部结构。我不认为 aMap会提高内存使用率,因为 Java 字符串已经尽可能地尝试指向内存中的相同地址。

我认为你应该修改你的设计。鉴于您的要求

输出屏幕的上半部分以 JTable 中的顺序显示文件中的每条记录,而下半部分显示基于该数据计算的统计信息

您不需要将整个文件存储在内存中。您需要完全阅读它来计算您的统计数据,这当然可以使用非常少量的内存来完成。关于 JTable 部分,这可以通过多种方式完成,而不需要为您的程序提供 2GB 的堆空间!我认为当有人想在内存中保留 CSV 时一定有问题!Apache IO LineIterator

于 2012-04-24T18:28:58.723 回答
0

增加 JVM 堆大小(-Xms 和 -Xmx)。如果你有记忆,这是最好的解决方案。如果您不能这样做,您将需要找到一种折衷方案,将数据模型和表示 (GUI) 更改结合起来,这通常会导致代码复杂性增加和潜在的错误。

  1. 尝试修改您的统计算法以在读取数据时完成它们的工作,而不是要求它全部存在于内存中。您可能会发现近似统计数据的算法就足够了。
  2. 如果您的数据包含许多重复的字符串文字,请使用 HashSet 创建缓存。请注意,缓存因内存泄漏而臭名昭著(例如,在加载不同文件之前不清除它们)。
  3. 减少图表上显示的数据量。具有大量数据的图形通常会在同一像素处或附近显示许多点。考虑通过合并 x 轴上相同位置处或附近的多个值来截断数据。例如,如果您的数据集包含 2,000,000 个点,其中大部分将与附近的其他点重合,因此您的底层数据模型不需要存储所有内容。
  4. 谨防信息过载。如果您的 JTable 包含 2GB 的数据,它对用户有意义吗?也许您应该对表格进行分页,并一次从文件中读取 1000 个条目以进行显示。
  5. 我很犹豫是否建议这样做,但在加载过程中,您可以将 CSV 数据转换为文件数据库(例如cdb)。您可以在转换过程中为图表积累统计数据并存储一些数据,并使用数据库一次快速读取一页数据,用于 JTable 如上所述。
于 2012-04-24T18:59:39.010 回答