首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java/Clojure中处理大型数据集: littleBig数据

在Java/Clojure中处理大型数据集: littleBig数据
EN

Stack Overflow用户
提问于 2010-08-04 15:45:36
回答 3查看 3.7K关注 0票数 10

我一直在使用Clojure开发一个图形/数据处理应用程序(你可以在这里看到截图) (不过,通常感觉我使用的是更多的Java,而不是Clojure),并且已经开始用更大的数据集测试我的应用程序。我对大约100k点没有问题,但是当我开始变得更高时,我会遇到堆空间问题。

现在,理论上,大约半个GB应该足够容纳大约7000万个双倍。当然,我正在做许多需要一些开销的事情,而且我可能同时在内存中保存2-3个数据副本,但我还没有优化太多,500 K左右的数据仍然比我应该能够加载的数据少几个数量级。

我知道Java对堆的大小有人为的限制(可以改变),我也知道可以在JVM启动时使用一些选项来改变这些限制。这就引出了我的第一个问题

  • 如果我使用的是JVM启动时的Swank-Clojure (通过Leiningen),那么我可以更改最大允许的堆空间吗?
  • 如果我将这个应用程序打包成一个Uberjar (就像我计划的那样),我能确保JVM有某种最小的堆空间吗?

但是,我并不满足于仅仅依靠JVM的堆来驱动我的应用程序。我不知道我最终可能处理的数据的大小,但它可能会达到数百万个点,也许堆无法容纳这一点。因此,我感兴趣的是寻找替代方案,而不是把数据堆在上面。以下是我的一些想法,和关于它们的问题:

  • 是否可以一次只读取大(文本)文件的一部分,这样我就可以一次导入和处理“块”中的数据,例如n行?如果是这样的话,是怎么做的?
  • 是否有更快的方式来访问我将读取的文件(可能很快,取决于实现),而不仅仅是一次读取它一点?如果你做过类似的事情,我想我在这里问的是过去对你有用的任何技巧/黑客。
  • 我是否可以从文件中“取样”;例如,只读取每一行z,从而有效地降低数据的采样量?

现在,我计划,如果上面有答案(我会继续搜索!),或者提供的洞察力会导致类似的解决方案,每次读取一大块数据,将其绘制到时间线(见截图-the时间线是绿色的),并允许用户只与该位进行交互,直到她单击next chunk (或其他什么),然后我将保存对文件所做的更改,并加载下一个“数据块”并显示出来。

或者,我会显示所有数据的整个时间线(向下采样,以便加载),但只允许每次在主窗口中访问其中的一个“块”(在绿色时间线之上查看的部分,如时间线中的viewport矩形所示)。

最重要的是,还有更好的方法吗?请注意,我不能对主窗口的数据进行降采样,因为我需要能够处理它并让用户与它交互(例如,单击一个点或附近的一个点来向该点添加一个“标记”:该标记是作为对该点的垂直规则绘制的)。

我会感谢任何洞察力,答案,建议或纠正!我也愿意用你喜欢的任何方式来阐述我的问题。

至少在一定程度上,这将是开源的;我想要一种简单而快速的方式来制作xy图,其中包含了Clojure世界中的大量数据。

编辑下采样只有在绘图时才有可能,而不是始终如此,这取决于所绘制的部分。我需要访问所有的数据来进行分析。(把它弄清楚!)虽然我确实应该考虑下采样,但我认为这一点也解决不了我的内存问题,因为我对图形所做的一切都是在BufferedImage上绘制的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-08-04 18:31:30

如果我使用的是JVM启动时的Swank-Clojure (通过Leiningen),那么我可以更改最大允许的堆空间吗?

您可以通过在启动时提供-Xms (最小堆)和-Xmx (最大堆)选项来更改文档堆大小,请参阅文档

因此,像java -Xms256m -Xmx1024m ...这样的东西将提供256 1GB的初始堆,并且可以选择增长到1GB。

我不使用Leiningen/Swank,但我希望可以更改它。如果没有其他的话,应该有一个Java启动脚本,您可以在其中更改参数。

如果我将这个应用程序打包成一个Uberjar (就像我计划的那样),我能确保JVM有某种最小的堆空间吗?

内存不是从jar文件中控制的,而是来自启动脚本,通常是调用java并提供参数的.sh或.bat文件。

我能否从文件中“示例”;例如,只读取每一行z行?

java.io.RandomAccessFile按字节索引提供随机文件访问,您可以在此基础上对内容进行示例。

是否可以一次只读取大(文本)文件的一部分,这样我就可以以“块”(例如,n行)每次导入和处理数据了吗?如果是这样的话,是怎么做的?

线-seq返回文件中每一行的懒惰序列,因此您可以一次处理任意数量的文件。

或者,在java.io - BufferedReader.readLine()FileInputStream.read(byte[] buffer)中使用Java机制。

是否有更快的方式来访问我将读取的文件(可能很快,取决于实现),而不仅仅是一次读取它一点?

在Java/Clojure中有BufferedReader,或者您可以维护自己的字节缓冲区并一次读取更大的块。

为了最大限度地利用您的内存,尽可能地保留数据。

对于一些实际数字,让我们假设您想要绘制音乐CD的内容:

  • 一张CD有两个通道,每个通道每秒有44,100个样本
    • 60分钟当时的音乐是3亿个数据点

  • 表示为每一个数据池:600 16的16位(2字节,一个短)
  • 表示为基本int数组(每个数据池4个字节):1.2GB
  • 表示为Integer数组(每个数据池32字节):10 32

使用这个博客中的对象大小数字(每个对象16字节开销,原始int 4字节,对象对8字节边界,数组中8字节指针= 32字节/整数)。

即使是600 at的数据,在一台“正常”计算机上同时保存在内存中也是一段很长的时间,因为您可能也会在其他地方使用大量的内存。但是,从原语到盒式数字的转换本身将使您可以在内存中保存的数据点的数量减少一个数量级。

如果您要在1900像素宽的“概述”时间线上绘制60分钟CD上的数据,那么您将有一个像素来显示2秒的音乐(大约180,000个数据点)。这显然太少,无法显示任何级别的细节,您可能需要某种形式的次抽样或汇总数据。

因此,您描述的解决方案--每次处理完整的数据集,以便在“概述”时间线中显示摘要,并且只保留内存中主“细节”窗口的小子集--听起来非常合理。

更新:

在快速文件读取:这篇文章乘以文件读取速度的13种不同的方式读取100 10的文件在Java - 结果从0.5秒到10分钟(!)。通常,读取速度快,缓冲区大小适中(4k到8k字节),每次读取一个字节(非常慢)。

这篇文章还有一个与C比较,以防有人感兴趣。(扰流板: Java读取速度最快的是C中内存映射文件的因子2)。

票数 7
EN

Stack Overflow用户

发布于 2010-08-04 17:11:27

从左边抛出一些想法..。

你可能会在柯尔特图书馆找到有用的东西。http://acs.lbl.gov/software/colt/

或者可能是内存映射的I/O。

票数 2
EN

Stack Overflow用户

发布于 2010-08-04 17:19:05

有几个想法:

  • 在Java/Clojure中处理内存中的大型数据集的最佳方法是使用大型原语数组。如果这样做,基本上只需要比基础数据的大小多一点内存。您可以在Clojure中使用aget/aset功能处理这些数组。
  • 我很想降低样本,但是如果需要的话,保持一种懒洋洋地访问细节点的方法,例如在用户交互的情况下。有点像谷歌地图让你看到整个世界的方式,只有当你放大的时候才加载细节.
  • 如果您只关心来自x图的输出映像,那么您可以通过一次加载几千个点(例如加载到原始数组中)来构造它,然后绘制它们,然后丢弃它们。这样,您就不需要在内存中保存完整的数据集。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3407277

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档