Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中哪种API用于文件读取以获得最佳性能?_Java_Performance_Api_Berkeley Db_Filereader - Fatal编程技术网

Java中哪种API用于文件读取以获得最佳性能?

Java中哪种API用于文件读取以获得最佳性能?,java,performance,api,berkeley-db,filereader,Java,Performance,Api,Berkeley Db,Filereader,在我工作的地方,以前每个文件都有超过百万行的文件。尽管服务器内存超过10GB,JVM为8GB,但有时服务器会挂起一会儿,并阻塞其他任务 我分析了代码,发现当文件读取内存使用频繁增加(1GB到3GB),然后突然恢复正常时。这种频繁的高内存和低内存使用似乎挂起了我的服务器。当然,这是由于垃圾收集 我应该使用哪个API来读取文件以获得更好的性能 现在我正在使用BufferedReader(新文件阅读器(…)来读取这些CSV文件 过程:我如何读取文件 我逐行阅读文件 每行有几列。根据类型,我相应地解析它

在我工作的地方,以前每个文件都有超过百万行的文件。尽管服务器内存超过10GB,JVM为8GB,但有时服务器会挂起一会儿,并阻塞其他任务

我分析了代码,发现当文件读取内存使用频繁增加(1GB到3GB),然后突然恢复正常时。这种频繁的高内存和低内存使用似乎挂起了我的服务器。当然,这是由于垃圾收集

我应该使用哪个API来读取文件以获得更好的性能

现在我正在使用
BufferedReader(新文件阅读器(…)
来读取这些CSV文件

过程:我如何读取文件

  • 我逐行阅读文件
  • 每行有几列。根据类型,我相应地解析它们(cost列为double,visit列为int,关键字列为String,等等)
  • 我将符合条件的内容(访问>0)推送到HashMap中,最后在任务结束时清除该映射
  • 更新

    我读取30或31个文件(一个月的数据),并将符合条件的数据存储在地图中。后来,这张地图被用来在不同的表格中找到一些罪犯。因此,读取数据是必须的,存储数据也是必须的。虽然我现在已经将HashMap部分切换到BerkeleyDB,但读取文件时的问题是相同的,甚至更糟

    我分析了代码,发现 而文件读取内存的使用在 千兆字节(1GB到3GB)和 然后突然恢复正常。信息技术 似乎这种频繁的高低 内存使用挂起我的服务器。属于 当然这是因为垃圾 收藏

    使用
    BufferedReader(新文件读取器(…)
    不会导致这种情况

    我怀疑问题在于您正在将行/行读入数组或列表,处理它们,然后丢弃数组/列表。这将导致内存使用量先增加,然后再次减少。如果是这种情况,您可以通过在读取每一行时处理每一行来减少内存使用

    编辑:我们一致认为问题在于内存中用于表示文件内容的空间。一个巨大的内存哈希表的替代方法是回到旧的“排序合并”方法,我们在计算机内存以KB为单位进行测量时使用了这种方法。(我假设处理由一个步骤控制,在该步骤中,您使用键K进行查找,以获得关联的行R。)

  • 如有必要,对每个输入文件进行预处理,以便它们可以按键K排序

  • 使用一个高效的文件排序实用程序将所有输入文件按K顺序排序。您希望使用一个使用经典合并排序算法的实用程序。这将 将每个文件拆分为可在内存中排序的较小块,对块进行排序,将它们写入临时文件,然后合并排序后的临时文件。UNIX/Linux
    sort
    实用程序是一个不错的选择

  • 并行读取已排序的文件,从所有文件中读取与每个键值相关的所有行,处理它们,然后转到下一个键值


  • 事实上,我有点惊讶使用BerkeleyDB没有帮助。但是,如果分析告诉您大部分时间都在构建数据库,那么您可以通过在构建数据库之前将输入文件(如上!)按升序排序来加快它的速度。(创建大型基于文件的索引时,如果按键顺序添加条目,则性能会更好。)

    BufferedReader是用于此目的的两个最佳API之一。如果您在读取文件时确实遇到问题,另一种方法可能是使用内存中的内容映射文件,然后直接从内存中读取内容

    但你的问题不在于读者。你的问题是每次读取操作都会创建一堆新对象,最有可能是在读取后所做的事情

    你应该考虑清理输入处理,注意减少所创建的对象的数量和/或大小,或者只是简单地在不再需要的时候快速清除对象。是否有可能一次只处理一行或一块文件,而不是将整个文件吸入内存进行处理

    另一种可能是处理垃圾收集。您有两种机制:

    • 每隔一段时间显式地调用垃圾收集器一次,比如说每10秒或每1000行输入或其他。这将增加GC所完成的工作量,但每个GC所花费的时间较少,内存不会膨胀太多,因此希望对服务器其余部分的影响较小

    • 摆弄JVM的垃圾收集器选项。这些在JVM之间有所不同,但是
      java-X
      应该给您一些提示

    更新:最有希望的方法:


    您真的需要一次在内存中处理整个数据集吗?

    尝试使用以下vm选项来调整gc(并进行一些gc打印):


    有益的评论。我已经在内存超过某个阈值时调用了GC,但这似乎对我没有帮助。您指出对象创建是罪魁祸首。可能是。正如我在stack trace中看到的一些BigDecimal类以及我创建的类一样。如果配置文件中有您以前不知道的数据类型,那么您很可能正在使用第三方库。可能是内存泄漏的罪魁祸首!不,一点也不。我使用的是整型、长型、双精度、文件、文件读取器、BufferedReader、line.split('\t',-1)、Map、HashMap以及Java标准库中的所有内容。我使用自己的类键和数据,每个类有4个变量。我按键聚合数据并将它们存储在HashMap中。显式GC是个坏主意。但是-XX:+DisableExplicitGC将删除该p
    -verbose:gc -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+PrintGCDetails -XX:+PrintGCTimeStamps