现在理论上,大约有一半的GB应该足以容纳7000万双打.当然,我正在做很多需要一些开销的事情,我实际上可以同时保存2-3个内存中的数据,但是我还没有优化,还有五十万左右的订单比我应该能够加载的更小.
我明白,Java对堆的大小有人为的限制(可以改变),我明白这些限制可以通过JVM启动时可以指定的选项进行更改.这导致我的第一个问题:
>如果我使用Swank-Clojure(通过Leiningen)启动JVM,我可以更改允许的最大堆空间吗?
>如果我打包这个应用程序(像我打算)作为Uberjar,我能确保我的JVM有一些最小的堆空间吗?
但是我不满足于依靠JVM的堆来为我的应用程序提供动力.我不知道我最终可以使用的数据的大小,但是可以达到数百万点,也许堆不能适应这个数据.因此,我很有兴趣找到只是打包数据的替代方法.这里有一些想法,有关他们的问题:
>一次只能读取一个大(文本)文件的一部分,因此我可以一次导入和处理“块”中的数据,例如n行?如果是这样,怎么办?
>是否有一些更快的访问文件的方式(可能会很快取决于实现),而不是简单地从它读取一点?我想我在这里询问过去为你工作过的任何技巧/黑客,如果你做了类似的事情.
>我可以从文件中“采样”例如只读每行z行,有效地对我的数据进行抽样?
现在我打算,如果有上述的答案(我会继续搜索),或提供的洞察力导致等效的解决方案,一次阅读大量数据,将其绘制到时间轴上(see the screenshot-the时间线是绿色的),并允许用户与该位进行交互,直到她点击下一个块(或某物),然后我将保存对文件所做的更改并加载下一个“块”数据并显示.
或者,我将显示所有数据的整个时间轴(下采样,所以我可以加载它),但只允许访问主窗口中一个“块”(在绿色上方查看的部分时间轴,如时间轴中的视口矩形所示).
最重要的是有更好的方法吗?请注意,我无法对主窗口的数据进行缩小,因为我需要处理它并让用户与之交互(例如,单击一个点或附近的点以添加“标记”到该点:该标记被绘制为在这一点上的垂直规则).
我会感谢任何见解,答案,建议或更正!我也愿意阐述
在任何你想要的问题上.
希望至少部分是开源的;我想要一个简单易用的快速方式,在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(max heap)选项来更改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有两个通道,每个通道每秒44,100个样本
> 60分钟的音乐就是约3亿的数据点
>每个数据点代表16位(2字节,短):600MB
>表示为原始int数组(每个数据点4个字节):1.2GB
>表示为整数数组(每个数据点32个字节):10GB
使用this blog中的数字对象大小(每个对象的16字节开销,原始int的4个字节,与8字节边界对齐的对象,数组中的8字节指针=每整数数据点32个字节).
即使是600MB的数据也是在“正常”的计算机上一次性保存在内存中,因为您可能会在其他地方使用大量的内存.但是,从原始到数字的转换本身将减少您可以在内存中保存一个数量级的数据点数.
如果要在1900像素宽的“概览”时间轴上从60分钟的CD中绘制数据,您将有一个像素显示两秒钟的音乐(约180,000个数据点).这显然无法显示任何级别的细节,您将需要某种形式的子采样或汇总数据.
所以您描述的解决方案 – 一次处理完整的数据集一个块,以便在“概述”时间轴中进行摘要显示,并保留内存中主“详细”窗口的小子集 – 听起来完全合理.
更新:
快速文件读取:This article次文件读取速度13种不同的方式读取一个100MB文件在Java – results从0.5秒到10分钟(!).一般来说,读取速度快,每次读取一个字节时,缓冲区大小(4k到8k字节)和(非常)慢.
该文章还有一个comparison to C,万一有人有兴趣. (Spoiler:最快的Java读取在C中的内存映射文件的2倍)