gpt4 book ai didi

java - 在Java/Clojure中处理大型数据集: littleBig data

转载 作者:IT王子 更新时间:2023-10-28 23:33:21 26 4
gpt4 key购买 nike

我一直在使用Clojure开发图形/数据处理应用程序(you can see a screenshot here)(尽管通常,我使用的Java比Clojure还要多),并且已经开始使用更大的数据集测试我的应用程序。大约100k点我没有问题,但是当我开始变得更高时,我遇到了堆空间问题。

现在,从理论上讲,大约一半的GB应该足以容纳大约7,000万个 double 。当然,我正在做很多事情,需要一些开销,实际上我可能同时在内存中保存了2-3个数据副本,但是我还没有做很多优化,大约500k仍然在订货数量级小于我应该能够加载的数量。

我了解Java对堆的大小有人为的限制(可以更改),并且我可以部分地更改这些限制,这些限制可以通过在JVM启动时指定的选项来进行。这使我想到了的第一个问题:

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

  • 但是我不满足于仅依靠JVM的堆来为我的应用程序供电。我不知道最终可能要使用的数据大小,但是它可能达到数百万个点,并且也许堆无法容纳这些数据。因此,在寻找替代方法以堆积数据方面,我很有趣。以下是我的一些想法 和有关它们的问题:
  • 是否可以一次只读取一个大(文本)文件的一部分,所以我可以一次以“块”形式导入和处理数据,例如一次n行?如果是这样,怎么办?
  • 除了一次简单地读取一次文件之外,是否有一些更快的方法来访问我将要读取的文件(可能很快,具体取决于实现方式)?我想我想问的是您过去做过的任何技巧/骇客,如果您做过类似的事情。
  • 我可以从文件中“采样”吗?例如仅读取每一个z行,有效地对我的数据进行下采样吗?

  • 现在,我计划,如果有上述答案(我将继续搜索!),或者提供的洞察力可以提供等效的解决方案,一次读取大量数据,然后将其绘制在时间轴上( see the screenshot –the时间轴为绿色),并允许用户与该位进行交互,直到她单击 next chunk(或其他内容)为止,然后我将保存对文件所做的更改并加载下一个“大块”数据并显示它。

    或者,我将显示所有数据的整个时间轴(已降采样,因此可以加载它),但是一次只允许在主窗口中访问其中一个“块”(在绿色上方查看的部分)时间轴,如时间轴中的视口(viewport)矩形所概述)。

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

    我将不胜感激,有任何见解,答案,建议或更正!我也很愿意讲
    您想以任何方式回答我的问题。

    希望这将至少部分是开源的;我想要一种易于使用但快速的方法来对Clojure世界中的许多数据进行xy绘制。

    编辑仅在绘制图形时才可能进行下采样,但并非总是如此,这取决于所绘制的零件。我需要访问所有数据以对其进行分析。 (只需清理一下即可!)尽管我绝对应该研究下采样,但我认为这至少不会解决我的内存问题,因为我要做的所有图形绘制工作都是在BufferedImage上进行的。

    最佳答案

    Can I change the maximum allowed heap space if I am using Swank-Clojure (via Leiningen) the JVM has on startup?



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

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

    我不使用Leiningen/Swank,但我希望可以更改它。如果没有其他问题,那么应该可以在其中更改参数的地方使用Java的启动脚本。

    If I package this application (like I plan to) as an Uberjar, would I be able to ensure my JVM has some kind of minimum heap space?



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

    Can I "sample" from the file; e.g. read only every z lines?



    java.io.RandomAccessFile通过字节索引提供对文件的随机访问,您可以在该索引的基础上对内容进行采样。

    Would it be possible to read in only parts of a large (text) file at a time, so I could import and process the data in "chunks", e.g, n lines at a time? If so, how?



    line-seq返回文件中每一行的惰性序列,因此您可以一次随意处理。

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

    Is there some faster way of accessing the file I'd be reading from (potentially rapidly, depending on the implementation), other than simply reading from it a bit at a time?



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

    要充分利用内存,请使数据尽可能原始。

    对于一些实际数字,假设您要绘制音乐CD的内容的图形:
  • CD包含两个 channel ,每个 channel 每秒具有44,100个样本
  • 60分钟。音乐的数量约为3亿个数据点
  • 每个数据点表示为16位(2字节,短):600MB
  • 表示为原始int数组(每个数据点4个字节):1.2GB
  • 表示为整数数组(每个数据点32字节):10GB

  • 使用 this blog中的数字表示对象大小(每个对象16字节开销,原始int 4字节,对齐8字节边界的对象,数组中的8字节指针=每个Integer数据点32字节)。

    即使是600MB的数据,也很难在“普通”计算机上一次全部保留在内存中,因为您可能还会在其他地方使用大量内存。但是,从原始数到带盒数的转换本身将减少您可以保留在内存中的数据点数量,数量级减少。

    如果要在1900像素宽的“概述”时间轴上绘制60分钟CD上的数据,您将需要一个像素来显示两秒钟的音乐(约180,000个数据点)。显然,这种方法太少了,无法显示任何详细程度,您可能需要在其中进行某种形式的二次抽样或汇总数据。

    因此,您描述的解决方案-一次处理整个数据集一个块,以便在“概述”时间轴中以摘要形式显示,并且仅将主“详细信息”窗口的一小部分保留在内存中-听起来非常合理。

    更新:

    对于快速文件读取: This article是用Java读取100MB文件的13种不同方式的文件读取速度的乘积- results从0.5秒到10分钟不等(!)。通常,读取速度快,缓冲区大小适中(4k至8k字节),一次读取一个字节时(非常)慢。

    如果有人感兴趣的话,本文还带有 comparison to C。 (扰流器:最快的Java读取速度是C中内存映射文件的2倍。)

    关于java - 在Java/Clojure中处理大型数据集: littleBig data,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3407277/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com