powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / NIO: OutOfMemoryError
4 сообщений из 29, страница 2 из 2
NIO: OutOfMemoryError
    #37922251
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коряво, но попробуйте сделать быстрее на NIO.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
import java.io.*;
import java.lang.System;
public class TestCopy {
  public static void main(String[] args) throws java.io.IOException {
    File[] fileList = new File(".").listFiles();
    byte[] buffer = new byte[1 * 1024 *1024];
    int files = 0, offset = 0, count = buffer.length;
    long millis = System.currentTimeMillis(), total = 0;
    BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(FileDescriptor.out), buffer.length);
    for ( File Item : fileList ) {
      if (Item.isDirectory() || (! Item.canRead())) continue;
      ++files;
      BufferedInputStream input = new BufferedInputStream(new FileInputStream(Item), buffer.length);
      total += Item.length();
      int readed;
      do {
        if (offset == buffer.length) {
          output.write(buffer);
          offset = 0;
          count = buffer.length;
        }
        readed = input.read(buffer, offset, count);
        if (readed < 0 ) {
          input.close();
        } else {
          offset += readed;
          count -= readed;
        }
      } while (readed >= 0);
    }
    if (offset > 0) {
      output.write(buffer, 0, offset);
    }
    output.close();
    millis = System.currentTimeMillis() - millis;
    System.err.println("Time (ms)   : " + millis);
    System.err.println("Files       : " + files);
    System.err.println("Bytes       : " + total);
    System.err.println("Speed (Kb/s): " + (long) (total+512)*1000/millis/1024);
  }
}

Использование stdout позволяет исключить "потери на запись" путём запуска "java TestCopy > nul"
Частный случай (java TestCopy > test.out):
Код: sql
1.
2.
3.
4.
Time (ms)   : 16999
Files       : 5487
Bytes       : 422251330
Speed (Kb/s): 24257
...
Рейтинг: 0 / 0
NIO: OutOfMemoryError
    #37923663
dgx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
dgx
Гость
OOsalivanвторой ответДа, тут понятно уже. transferTo() пытается сразу целиком отобразить исходный файл на память (вызывается фунция ОС CreateFileMapping, затем MapViewOfFile с количеством байт равным длине файла), и для этих 84Мб, судя по всему, не получается найти непрерывный диапазон адресов из-за фрагментации. Не совсем еще понятно, почему диапазоны не освобождаются, но общая картина складывается как-то так.

Basil A. SidorovКоряво, но попробуйте сделать быстрее на NIO.Две процедуры копирования файла:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
  public static byte[] buffer = new byte[1*1024*1024];
  public static void copy1(FileInputStream fi, FileOutputStream fo) throws Exception {
    BufferedInputStream input = new BufferedInputStream(fi, buffer.length);
    BufferedOutputStream output = new BufferedOutputStream(fo, buffer.length);
    int offset = 0;
    int count = buffer.length;
    int readed;
    do {
      if (offset == buffer.length) {
        output.write(buffer);
        offset = 0;
        count = buffer.length;
      }
      readed = input.read(buffer, offset, count);
      if (readed > 0) {
        offset += readed;
        count -= readed;
      }
    } while (readed >= 0);
    if (offset > 0) {
      output.write(buffer, 0, offset);
    }
    output.flush();
  }

  public static void copy2(FileInputStream fi, FileOutputStream fo) throws Exception {
    long bytesTotal = 0;
    FileChannel fileFrom = fi.getChannel();
    while (bytesTotal < fileFrom.size()) bytesTotal += fileFrom.transferTo(bytesTotal, 1*1024*1024, fo.getChannel());
  }

copy1 - я вынес код копирования в отдельный метод, copy2 - сделал через NIO.

Поочередный запуск, 20 тыс.файлов суммарным объемом 3,3 Гб объединяются в один (время в секундах):

copy1 - 512,7
copy2 - 313,4
copy1 - 389,5
copy2 - 304,6
copy1 - 384,7
copy2 - 308,2

По три запуска, 10 тыс.файлов суммарным объемом 1,7 Гб:

copy1 - 193,9
copy1 - 195,9
copy1 - 194,6

copy2 - 152,5
copy2 - 153,1
copy2 - 152,3

Т.е. после заполнения кэша, время выполнения copy1 стабильно на 25-30% превышает время выполнения copy2.

Basil A. SidorovКогда требуется объединить тысячи файлов в один, то никакой метод копирования не позволит не то чтобы убрать, а просто уменьшить накладные расходы на открытие файлов.Судя по полученным результатам, это утверждение не соответствует действительности.
Basil A. SidorovЯ повторно озвучу размер буфера, который будет оптимальным для вашей задачи: один-два мегабайта .
... позволяет (лишь) сократить накладные расходы по копированию данных в памяти.Вот несколько решений, лежащих в основе ОС Windows:
1. Чтение-запись данных файла, file mapping и своп памяти реализуются одним и тем же средством диспетчера памяти;
2. Трансляция виртуальных адресов обеспечивает проецирование данных файлов на адресное пространство процессов (одного или нескольких);
3. Драйверы файловых систем не имеют собственного кэша, а пользуются системным кэшем, поддерживающим виртуальные блоки (смещения внутри файлов, а не дисковых разделов).

Пострайтесь понять разницу между копированием данных в памяти и отображением одной и той же памяти на разные адреса и в разные процессы.
Как это может влиять общую на производительность системы, с учетом медленных дисковых устройств, я написал в предыдущем сообщении.

P.S. У меня нет желания Вам что-то доказывать и в чем-то убеждать. Надеюсь на взаимопонимание.
...
Рейтинг: 0 / 0
NIO: OutOfMemoryError
    #37923860
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dgxP.S. У меня нет желания Вам что-то доказывать и в чем-то убеждать.Последний вопрос - почему в одной функции есть flush(), а в другой - нет?
...
Рейтинг: 0 / 0
NIO: OutOfMemoryError
    #37923862
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не, не последний...
Вы проверяли, что размер целевого файла совпадает с суммой размеров исходных?
...
Рейтинг: 0 / 0
4 сообщений из 29, страница 2 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / NIO: OutOfMemoryError
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]