Я прочитал около 7 ГБ файлов XML (~ 15 КБ каждый) с помощью Java NIO.И преобразовать их позже с JAXB.После обработки всех файлов (~ 12 минут) и правильного закрытия приложения мне любопытно, что потребляет около 16 ГБ памяти на моем компьютере с Windows 10.
RamMap (Sysinternals) показывает, что Mapped File потребляет большинство.На самом деле мои системы хранят все (?) Обработанные файлы в памяти.Но это использование памяти перечислено под любым процессом, который Windows Resource-Monitor может показать мне.
Однако, если я перезапущу свое приложение (через Eclipse), я вижу, что мои Коллекции все еще находятся на том же объектном адресе.Поэтому запуск приложения во второй раз изменит узкое место с жесткого диска на процессор.
Память освобождается только при перезагрузке системы.Выйти не сделает этого.Так как я хочу сравнить различные способы выполнения ввода-вывода с помощью Java на моем компьютере, это вызывает беспокойство.
Мой конвейер обрабатывает одну папку полностью, прежде чем начинать со следующей.
getAllFolders
чтобы собрать папки (~ 300), которые я хочу обработать getAllFilesInFolder
, чтобы собрать все файлы (~ 2k á 15kb) под ним (рекурсивно) unmarshal
все файлы (~2k), собранные getAllFilesInFolder
в параллельном потоке - , преобразование
List<MyXml>
в один MyXml
marshal
MyXml
- Начало со следующей папки
Следующие методы обрабатывают создание List<Path>
, которое используется для демаршаллинга.
// Method returns all Folders inside the entryPath
public List<Path> getAllFolders(Path entryPath) {
List<Path> folderList = Collections.synchronizedList(new ArrayList<Path>());
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(entryPath)) {
for (Path path : directoryStream) {
if (Files.isDirectory(path)) {
folderList.add(path);
}
}
}
return folderList;
}
// Method returns all regular Files inside the path
public List<Path> getAllFilesInFolder(Path path){
try (Stream<Path> files = Files.walk(path).filter(Files::isRegularFile)) {
return files.collect(Collectors.toList());
}
return null;
}
Выполнение этих вместе в одиночку занимает около 2 минут и, по-видимому, не является причиной длябольшой файл mmap.
Кажется, что корневой курс находится в маршаллинге / демаршаллинге:
public class XmlMarshaller {
private JAXBContext jaxbContext;
private XmlMarshaller() {
jaxbContext = JAXBContext.newInstance(MyXml.class);
}
private static class LazyHolder {
private static final XmlMarshaller INSTANCE = new XmlMarshaller();
}
public static XmlMarshaller getInstance() {
return LazyHolder.INSTANCE;
}
public void marshal(MyXml xml, Path output) {
try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(output), StandardCharsets.UTF_8)) {
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.toString());
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(xml, osw);
}
}
public MyXml unmarshal(Path file) {
MyXml xml = null;
try (InputStreamReader isr = new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)) {
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
xml = (MyXml) unmarshaller
.unmarshal(isr);
}
return xml;
}
}
Я удалил операторы catch(){...}
для лучшей читаемости.
AmЯ правильно обрабатываю потоки ввода / вывода?Могу ли я получить утечку ресурсов?Или Windows 10 здесь оптимизирует?