我有一个Java
项目,其中包含大量XML文件(> 500)。在运行时读取这些文件会导致性能问题。
是否可以选择将所有XML文件加载到RAM并从那里读取而不是磁盘?
我知道有像RamDisk这样的产品,但这个是商业工具。
我可以使用任何现有的Java API /库将XML文件复制到主内存并从主内存中读取吗?
答案 0 :(得分:5)
我首先尝试内存映射文件,由标准java库中的RandomAccessFile
和FileChannel
提供。通过这种方式,操作系统可以将常用的文件内容保存在内存中,从而有效地实现您的目标。
答案 1 :(得分:4)
您可以使用内存数据库来存储中间文件(XML文件)。这将提供使用ram和db的速度。
供参考使用以下链接:
在内存数据库中使用H2:
http://www.javatips.net/blog/2014/07/h2-in-memory-database-example
答案 2 :(得分:2)
使用 Label[] lbl ;
private void setupControls()
{
int Totallbl = 5;
int height = 30;
lbl = new Label[Totallbl];
try
{
for (int i = 0; i < Totallbl; i++)
{
lbl[i] = new Label();
lbl[i].Location = new Point(20, ((i + 1) * height));
lbl[i].Name = "lbl" + i;
lbl[i].Text = "LabelText";
lbl[i].AutoSize = true;
this.Controls.Add(lbl[i]);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
课程。它的行为类似于存储在文件系统中的大量字节。此类的实例支持读取和写入随机访问文件。
另外我建议使用java.io.RandomAccessFile
直接从磁盘读取文件,而不是将其加载到内存中。
MemoryMappedFile
然后你可以照常阅读缓冲区。
答案 3 :(得分:0)
您是否考虑过为这些文件创建对象结构并对其进行序列化,java对象序列化和反序列化比解析XML要快得多,这再次考虑到这些500个左右的XML文件在读取之间不会被修改
here is an article讨论序列化和反序列化。
如果担心要将文件内容加载到内存中,那么考虑ByteArrayInputStream
,ByteArrayOutputStream
类甚至可以使用ByteBuffer
,这些可以将字节存储在内存中
答案 4 :(得分:0)
Java对象序列化/反序列化通常不比XML编写和解析快。当涉及大量对象时,Java序列化/反序列化实际上效率非常低,因为它跟踪每个单独的对象(因此重复的引用不会被多次序列化)。这对于对象网络非常有用,但对于简单的树结构,它会增加很多开销而没有增益。
您最好的方法可能是使用快速技术来处理XML(例如javax.xml.stream.XMLStreamReader
)。除非文件很大,否则加载XML文件的时间超过30-40秒 - 您可能正在使用低效的方法来处理XML,例如将它们加载到DOM中。您还可以尝试并行读取多个文件(例如使用Java 8并行流)。
答案 5 :(得分:0)
看起来您的主要问题是大量文件,RAM不是问题。你能证实吗?
是否可以执行预处理步骤,使用某种分隔符附加所有这些文件并创建一个大文件?这样,您可以增加读取的块大小,并避免磁盘搜索的性能损失。
答案 6 :(得分:0)
您是否考虑过压缩XML文件并读取这些压缩的XML文件?压缩的XML可能只有原始或更好的3-5%。当用户可以看到它时,您可以将其解压缩,然后再次压缩存储以供进一步阅读。
这是我发现可能有用的库: zip4j
答案 7 :(得分:0)
这取决于您是否多次读取数据。
假设我们使用某种基于Java的RamDisk(它实际上是某种缓冲区或字节数组)。
进一步假设处理数据的时间少于读取数据。所以你必须至少读一次。因此,如果您首先从磁盘到内存读取它,然后从内存中处理它,那将没有任何区别。
如果您不止一次读取文件,可以将所有文件读入内存(各种选项,缓冲区,字节数组,自定义文件系统......)。
如果处理时间比读取时长(似乎不是这种情况),您可以使用单独的线程从磁盘预取文件 - 并使用另一个线程处理内存中的数据。