Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Быстрое копирование большого количества файлов 
V
    Опции темы
XperT
Дата 1.5.2012, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Бьюсь сейчас над решением задачи быстрого копирования большого количества файлов. Ситуация такова, что при использовании функции CopyFileEx на файлах в количестве 30 000 программе необходимо около 6 мин, в то время, как копирование этих же файлов с помощью проводника отнимает чуть больше полторы минуты.

Подозреваю, что всё дело в том, что ОС это делает в несколько потоков, потому вижу 2 варианта решения проблемы:
1. Самому делать в это в несколько потоков (не факт, что сработает, так как возможно, что все запросы на копирование файлов с помощью функции CopyFileEx становятся в очередь)

2. Найти функцию, которая отправляет на копирование не один файл, а группу файлов, чтобы ОС сама могла распределять свои ресурсы для самого оптимального копирования

Более предпочтительным есть второй вариант, но не уверен, что в WinAPI найдется подобная функция. Если кто-то знает о её существовании или имеет еще какие-то варианты решения проблемы - буду очень признателен.
PM MAIL   Вверх
kami
Дата 1.5.2012, 14:10 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 15
Всего: 72



Цитата(XperT @  1.5.2012,  11:51 Найти цитируемый пост)
но не уверен, что в WinAPI найдется подобная функция. 

SHFileOperation
PM MAIL WWW   Вверх
XperT
Дата 1.5.2012, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Цитата(kami @ 1.5.2012,  14:10)
Цитата(XperT @  1.5.2012,  11:51 Найти цитируемый пост)
но не уверен, что в WinAPI найдется подобная функция. 

SHFileOperation

К сожалению скорость от использования этой функции не выросла: во-первых очень медленно проходит подготовка файлов (секунд 30-40), по всей видимости в это время парсится входящая строка, а во вторых скорость копирования такая же как при использовании CopyFileEx (в окне копирования пишет 1,26 МБ/сек, при том, что во время копирования через проводник скорость 5 МБ/сек).

Может кто-то знает другие способы быстрого копирования файлов?
PM MAIL   Вверх
kami
Дата 1.5.2012, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 15
Всего: 72



Цитата(XperT @  1.5.2012,  17:31 Найти цитируемый пост)
при том, что во время копирования через проводник скорость 5 МБ/сек).

Как происходит тестирование?
Сперва - своя программа, потом - проводник?

Для чистоты эксперимента не помешает перезагрузка компьютера между замерами. В противном случае винда может закешировать файлы, и в результате второй "забег" окажется гораздо быстрее.
PM MAIL WWW   Вверх
Keeper89
Дата 1.5.2012, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



Цитата(kami @  1.5.2012,  20:49 Найти цитируемый пост)
Для чистоты эксперимента не помешает перезагрузка компьютера между замерами. В противном случае винда может закешировать файлы, и в результате второй "забег" окажется гораздо быстрее. 

А можно попробовать наоборот, сначала проводник, а потом программа.


--------------------
PM MAIL WWW   Вверх
XperT
Дата 1.5.2012, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Попробовал наоборот, ничего не поменялось, проводник копирует минимум в 5 раз быстрее
PM MAIL   Вверх
Keeper89
Дата 1.5.2012, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2580
Регистрация: 26.2.2009

Репутация: 14
Всего: 58



XperT, покажи код.


--------------------
PM MAIL WWW   Вверх
XperT
Дата 1.5.2012, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Класс делал с заделом на будущее:
Код

unit FastFileProccessingClass;

interface

uses SysUtils, Windows, Classes, ShellApi;

type
  TBuffer = array of Char;

  TFileProccessing = class
  private
    FMultiDest : boolean;
    FHandle : Cardinal;

    FilesList : TStringList;
    DestList : TStringList;

    procedure CreateBuffer( Names : TStringList; var P : TBuffer );
  public
    constructor Create(Hwnd : Cardinal; multi_dest : boolean = false);  overload;
    destructor Destroy(); override;

    procedure Clear();
    function  Count():integer;

    procedure AddFileDest(file_path, dest_folder:string);
    procedure AddFile(file_path : string);
    procedure SetDestination(dest_folder : string);

    function CopyFiles():boolean;
  end;

implementation

{ TFileProccessing }

procedure TFileProccessing.AddFile(file_path: string);
begin
  if FMultiDest then raise Exception.Create('Can''t use single adding files in multidest mode');

  FilesList.Add(file_path);
end;

procedure TFileProccessing.AddFileDest(file_path, dest_folder: string);
begin
  FilesList.Add(file_path);
  DestList.Add(dest_folder);
end;

procedure TFileProccessing.Clear;
begin
  FilesList.Clear;
  DestList.Clear;
end;

function TFileProccessing.CopyFiles: boolean;
var
  SHFileOpStruct : TSHFileOpStruct;
  SrcBuf, DestBuf : TBuffer;
begin
  if DestList.Count = 0 then raise Exception.Create('Destination folder is not selected!');
  if FilesList.Count = 0 then raise Exception.Create('There is no files for coping!');

  CreateBuffer( FilesList, SrcBuf );
  CreateBuffer( DestList, DestBuf );

  with SHFileOpStruct do
  begin
    Wnd := FHandle;
    wFunc := FO_COPY;
    pFrom := Pointer( SrcBuf );
    pTo := Pointer( DestBuf );

    fFlags := FOF_NOCONFIRMMKDIR;
    if FMultiDest then fFlags := fFlags OR FOF_MULTIDESTFILES;

    fAnyOperationsAborted := False;
    hNameMappings := nil;
    lpszProgressTitle := nil;
  end;

  Result := SHFileOperation( SHFileOpStruct ) = 0;

  SrcBuf := nil;
  DestBuf := nil;
  Clear();
end;

function TFileProccessing.Count: integer;
begin
  result := FilesList.Count;
end;

constructor TFileProccessing.Create(Hwnd : Cardinal; multi_dest : boolean = false);
begin
  FMultiDest := multi_dest;
  FHandle := Hwnd;

  FilesList := TStringList.Create;
  DestList := TStringList.Create;
end;

procedure TFileProccessing.CreateBuffer(Names: TStringList; var P: TBuffer);
var
  i, j, a : integer;
  buf : string;
begin
  SetLength(P, length(Names.Text) - Names.Count + 1);

  a := 0;
  for i := 0 to Names.Count - 1 do
  begin
    buf := Names.Strings[i];
    for j := 1 to length(buf) do
    begin
      P[a] := buf[j];
      inc(a);
    end;

    P[a] := #0;
    inc(a);
  end;

  P[a] := #0;
end;

destructor TFileProccessing.Destroy;
begin
  FilesList.Free;
  DestList.Free;

  inherited;
end;

procedure TFileProccessing.SetDestination(dest_folder: string);
begin
  if FMultiDest then raise Exception.Create('Can''t use single set destination in multidest mode');

  DestList.Text := dest_folder;
end;

end.


Проверял на таком коде:
Код

...
for i := 0 to Files.Count - 1 do
  FileProccessing.AddFile(Files.Strings[i]);

FileProccessing.SetDestination('D:\TMP');
FileProccessing.CopyFiles();
...

PM MAIL   Вверх
northener
Дата 2.5.2012, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: нет
Всего: 20



Смущает меня то, что сравнивается не время копирования а "значение скорости копирования" выдаваемое окном визуализации процесса копирования.
И ещё одно смущает. В методе TFileProccessing.CopyFiles структура SHFileOpStruct - локальная переменная, но никакого предварительного обнуления сей структуры не производится. Следовательно некоторые поля этой структуры явно задаются в коде метода, а прочие остаются на усмотрение Александра Сергеевича.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
XperT
Дата 2.5.2012, 10:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Цитата

Смущает меня то, что сравнивается не время копирования а "значение скорости копирования" выдаваемое окном визуализации процесса копирования.

Проводник копирует за 1-1,5 мин, программа за 6-7 мин. Точных вычислений не делал, и так прекрасно видно, что разница в скорости очень большая. В посте приводил данные по скорости копирования из окна копирования потому, что соотношения соотвествуют временным.

Цитата

И ещё одно смущает. В методе TFileProccessing.CopyFiles структура SHFileOpStruct - локальная переменная, но никакого предварительного обнуления сей структуры не производится. Следовательно некоторые поля этой структуры явно задаются в коде метода, а прочие остаются на усмотрение Александра Сергеевича. 

Какие прочие? Все свойства структуры заполнены, проверял через дебагер.
PM MAIL   Вверх
XperT
Дата 2.5.2012, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



После перезагрузки провел еще один эксперимент: сначала копировал проводником, потом через программу.
Проводник:
Процесс копирования запустился сразу, без задержек на оценку. Продолжительность копирования: 2 мин 50 сек

Программа:
1. Сначала запустилась оценка:
user posted image
Это продолжалось 48 сек.

2. Потом запустилось само копирование. Продолжительность ~ 2 мин

3. Под конец копирования окошко подвисло в таком состоянии:
user posted image
Длилось это 3 мин 39 сек

Итого: 6 мин 27 сек против 2 мин 50 сек
PM MAIL   Вверх
northener
Дата 2.5.2012, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: нет
Всего: 20



Цитата(XperT @  2.5.2012,  10:45 Найти цитируемый пост)
Какие прочие? Все свойства структуры заполнены, проверял через дебагер. 

Чем они заполнены, если вы сами их не заполняли? Мусором? 


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
XperT
Дата 2.5.2012, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Цитата(northener @ 2.5.2012,  17:07)
Цитата(XperT @  2.5.2012,  10:45 Найти цитируемый пост)
Какие прочие? Все свойства структуры заполнены, проверял через дебагер. 

Чем они заполнены, если вы сами их не заполняли? Мусором?

Кто они? Вы видели описание структуры? Покажите мне хоть одно свойство которое я не заполняю?
PM MAIL   Вверх
northener
Дата 2.5.2012, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: нет
Всего: 20



Цитата(XperT @  2.5.2012,  17:30 Найти цитируемый пост)
Покажите мне хоть одно свойство которое я не заполняю? 

Да. Был не прав, признаю.

Цитата(XperT @  2.5.2012,  14:29 Найти цитируемый пост)
3. Под конец копирования окошко подвисло в таком состоянии:

Значит надо попробовать разобраться из-за чего происходит это подвисание. Ибо весь остальной процесс выполняется за такое же время как и процесс копирования в проводнике.


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
XperT
Дата 3.5.2012, 00:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 269
Регистрация: 19.8.2006

Репутация: 1
Всего: 4



Цитата

Значит надо попробовать разобраться из-за чего происходит это подвисание. Ибо весь остальной процесс выполняется за такое же время как и процесс копирования в проводнике. 

Не совсем весь, первый пункт так же не наблюдается в проводнике. Вроде и мигает в нём что-то вроде оценки, но буквально на пол секунды, а тут почти минута. Я предполагаю, что идёт парсинг передаваемой строки, вопрос только почему так медленно. Да и в ряд ли тут что-то поделаешь, не так много в этой функции свойств и флагов, чтобы можно было экспериментировать и искать оптимальные варианты, а больше по сути ничего и не сделаешь.

В любом случае проблему решил другим путем: копирование файлов через CopyFileEx в несколько потоков. Опытным путем было вычислено, что при разбиении списка файлов на 3 равных части и копирования каждой в отдельном потоке даёт самую оптимальную скорость. На тех же файлах скорости копирования находится в диапазоне 120-150 сек. Увеличивание количества потоков даёт очень маленький прирост (скорее всего всё дело упирается в скорость работы винта, что собственно и требовалось сделать).

Тему можно считать закрытой.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1064 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.