powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно "прибить" копирующий поток?
25 сообщений из 61, страница 2 из 3
Как правильно "прибить" копирующий поток?
    #39471493
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
misha mikem52Вы просто наверное не в курсе, что самая быстрая функция копирования - это именно CopyFile, особенно, по локальной сети (не CopyFileEx и не вручную по-блочно). CopyFile была выбрана из соображения скорости копирования.
Работа с диском (сетью) -- это всегда работа с диском (сетью) и никаких чудес тут не бывает. Думаете эта функция волшебная?

Единственный способ заметно ускорить копирование -- совместить во времени чтение следующего блока из источника с записью предыдущего блока на назначение. Это ускорит процесс при условии, что источник и назначение -- не одно устройство, и они не находятся за общим узким каналом связи.

Неужели так трудно реализовать этот простой алгоритм и нужно плодить говнософт, который киляет активные потоки и оставляет заблокированные файлы в системе? Вы с выбором профессии не ошиблись?

Кстати, помнится, по бенчмаркам плагин bcopy для FAR Manager даже несколько быстрее, чем CopyFile. Вот где настоящая магия!

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
 do
            {
              if(UpdatePosInfo(0ULL,subadd)) break;
              if(!MyReadFile(hIn,buff,sizeof(buff),&dReaded,NULL,flags))
              {
                Log(L"ReadFile",src,NULL); Ok=FALSE; break;
              }
              subadd+=dReaded;
              if(!MyWriteFile(hOut,buff,dReaded,&dWritten,NULL,flags))
              {
                Log(L"WriteFile",dest,NULL); Ok=FALSE; break;
              }
} while(dReaded==sizeof(buff));




...

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
static BOOL MyReadFile(HANDLE hFile,PVOID lpBuffer,DWORD nNumberOfBytesToRead,PDWORD lpNumberOfBytesRead,LPOVERLAPPED lpOverlapped,DWORD *flags)
{
  WRAPPER_PROLOG(0,BOOL)
  ReadFile(hFile,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped);
  WRAPPER_EPILOG(0,ERROR_SUCCESS)
}

static BOOL MyWriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite,PDWORD lpNumberOfBytesWritten,LPOVERLAPPED lpOverlapped,DWORD *flags)
{
  WRAPPER_PROLOG(0,BOOL)
  WriteFile(hFile,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWritten,lpOverlapped);
  WRAPPER_EPILOG(0,ERROR_SUCCESS)
}
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471494
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДНяшик,

ничем не обоснованные фантазии.

Да ты что!) Смотри выше, а человек говорит работает быстрее и чудеса!) А такая же реализация
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471501
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няшик, а может и CopyFileEx3 , не помню уже. Но речь как бы не о плагинах.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471520
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m52Вы просто наверное не в курсе, что самая быстрая функция копирования - это именно CopyFile, особенно, по локальной сети (не CopyFileEx и не вручную по-блочно). CopyFile была выбрана из соображения скорости копирования.
Вот не поленился, взял исходники Windows, и знаете, что я там нашел? Именно то, что и без исходников понятно любому нормальному человеку.
\private\windows\base\client\fileopcr.c
Код: plaintext
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.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
BOOL
WINAPI
CopyFileW(
    LPCWSTR lpExistingFileName,
    LPCWSTR lpNewFileName,
    BOOL bFailIfExists
    )

/*++

Routine Description:

    A file, its extended attributes, alternate data streams, and any other
    attributes can be copied using CopyFile.

Arguments:

    lpExistingFileName - Supplies the name of an existing file that is to be
        copied.

    lpNewFileName - Supplies the name where a copy of the existing
        files data and attributes are to be stored.

    bFailIfExists - Supplies a flag that indicates how this operation is
        to proceed if the specified new file already exists.  A value of
        TRUE specifies that this call is to fail.  A value of FALSE
        causes the call to the function to succeed whether or not the
        specified new file exists.

Return Value:

    TRUE - The operation was successful.

    FALSE/NULL - The operation failed. Extended error status is available
        using GetLastError.

--*/

{
    BOOL b;

    b = CopyFileExW(
            lpExistingFileName,
            lpNewFileName,
            (LPPROGRESS_ROUTINE)NULL,
            (LPVOID)NULL,
            (LPBOOL)NULL,
            bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0
            );

    return b;
}


Оказывается, что ваша "мегабыстрая" CopyFile внутри невозбранно вызывает "тормознутую" CopyFileEx.
Вот это поворот, не правда ли?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471522
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
misha mikeНяшик, а может и CopyFileEx3 , не помню уже. Но речь как бы не о плагинах.

Выглядит очень сложным, и нагромождённым... Скорее первый вариант
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471551
Жышы
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
misha mikem52Вы просто наверное не в курсе, что самая быстрая функция копирования - это именно CopyFile, особенно, по локальной сети (не CopyFileEx и не вручную по-блочно). CopyFile была выбрана из соображения скорости копирования.
Вот не поленился, взял исходники Windows, и знаете, что я там нашел? Именно то, что и без исходников понятно любому нормальному человеку.
\private\windows\base\client\fileopcr.c
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
...

{
    BOOL b;

    b = CopyFileExW(
            lpExistingFileName,
            lpNewFileName,
            (LPPROGRESS_ROUTINE)NULL,
            (LPVOID)NULL,
            (LPBOOL)NULL,
            bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0
            );

    return b;
}


Оказывается, что ваша "мегабыстрая" CopyFile внутри невозбранно вызывает "тормознутую" CopyFileEx.
Вот это поворот, не правда ли?

Вполне возможно, что ТС, испытывая CopyFileEx, воткнул в нее тормозную LPPROGRESS_ROUTINE.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471556
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЖышыВполне возможно, что ТС, испытывая CopyFileEx, воткнул в нее тормозную LPPROGRESS_ROUTINE.
Это из какого места должны расти руки, что тормозным сделать проверку одного булевого флага?
Ему ж, вроде, только возможность прерывания нужна, даже не контроль прогресса копирования.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471670
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вы, кстати, ради интереса сделаете простое приложение с вызовом
Код: pascal
1.
CopyFile(Source, Dest)


и
Код: pascal
1.
CopyFileEx(Source, Dest, nil, nil, nil, 0);


и замером времени их выполнения.

И натравите его на какой-нибудь файл метров 300+ в локалке.
Будете очень удивлены, особенно если у вас Windows 10.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471689
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpБудете очень удивлены, особенно если у вас Windows 10.
Блин, откуда вы такие беретесь? Win10, сверху весь код CopyFileW, снизу начало CopyFileEx, для особо догадливых все важное выделено цветом.

И чему мне удивляться? Тому, что после первого копирования файл банально закешируется и второе копирование будет выполнено мгновенно?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471699
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpВы, кстати, ради интереса сделаете простое приложение с вызовом
Код: pascal
1.
CopyFile(Source, Dest)


и
Код: pascal
1.
CopyFileEx(Source, Dest, nil, nil, nil, 0);


и замером времени их выполнения.

И натравите его на какой-нибудь файл метров 300+ в локалке.
Будете очень удивлены, особенно если у вас Windows 10.

misha mike...
Блин, откуда вы такие беретесь?
...


Меньше эмоций, больше тестов.

Ну, кто первым тест прогонит?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471700
Жышы
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
misha mikeЖышыВполне возможно, что ТС, испытывая CopyFileEx, воткнул в нее тормозную LPPROGRESS_ROUTINE.
Это из какого места должны расти руки, что тормозным сделать проверку одного булевого флага?
Ему ж, вроде, только возможность прерывания нужна, даже не контроль прогресса копирования.

Это не булевский флаг, а коллбэк. И мы не знаем, что там ТС накодил. Видимо, что-то ужасное, не зря второй год мучается.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471711
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДМеньше эмоций, больше тестов.

Ну, кто первым тест прогонит?

Вот тебе школьная загадка из разряда какой поезд придёт раньше.

Есть две функции, А и Б. Функция А вызывает функцию Б а функция Б вызывает основный код.

Вопрос: Какая функция выполниться быстрее, А или Б
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471716
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няшик,

тут одни люди утверждают, что одно быстрее другого, а другие возражают. По факту - голословно, и те и другие.
Тесты и их результаты никто не представил.
Кто-то на исходники вайна ссылается, кто-то вообще на исходники непонятно чего, кто-то - на конкретную версию Windows.

Какой смысл спора, если есть одни лишь утверждения, но ни тестов, ни их результатов нет?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471722
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДКакой смысл спора, если есть одни лишь утверждения, но ни тестов, ни их результатов нет?
Т.е. для уверенности, что 2*2=4 недостаточно знания таблицы умножения, нужно проводить масштабное тестирование?

Я показал исходник Windows 2000 (да это он), проверил в отладчике живые Windows 7 и Windows 10, показал результат дизассемблирования. И нигде не нашел никаких причин, чтобы CopyFile работала быстрее CopyFileEx.

В противовес мне выдвигаются какие-то голословные утверждения о том, что функция A, использующая в качестве реализации функцию B, должна быть быстрее ее прямого вызова. Предлагают сделать тест, который невозможно провести объективно в силу целого ряда факторов.

Это форум программистов или двач какой-то?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471724
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДНяшик,

тут одни люди утверждают, что одно быстрее другого, а другие возражают. По факту - голословно, и те и другие.
Тесты и их результаты никто не представил.
Кто-то на исходники вайна ссылается, кто-то вообще на исходники непонятно чего, кто-то - на конкретную версию Windows.

Какой смысл спора, если есть одни лишь утверждения, но ни тестов, ни их результатов нет?

Это всё из за незнания. Во первых - есть заполнения стэка аргументов, +1 вызов

Вот приведу пример, как 1 лишний вызов даёт просад в 1.2 %

B:
0.007186 сек.
A:
0.008768 сек.

Код: pascal
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.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
program Project1;

{$R *.res}

uses
  windows, system.SysUtils;

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer; cdecl;
  varargs; external 'msvcrt.dll';

function B(r: Integer): Integer;
begin
  Result := r;
end;

function A(r: Integer): Integer;
begin
  Result := B(r);
end;

// Измерительные функции
procedure Start(var startTime: int64);
begin
  QueryPerformanceCounter(startTime);
end;

function Stop(startTime, stopTime, iCounterPerSec: int64): AnsiString;
var
  time: Single;
begin
  if QueryPerformanceCounter(stopTime) then
  begin
    QueryPerformanceFrequency(iCounterPerSec);

    time := (0 - startTime + stopTime) / iCounterPerSec;

    SetLength(Result, 15);

    SetLength(Result, sprintf(PAnsiChar(Result), '%f сек.', time));
  end;
end;

var
  startTime, stopTime, iCounterPerSec: int64;
  I: Cardinal;
  Output: AnsiString;

  v: Integer;

begin
  try

    Writeln('B:');

    Start(startTime);

    for I := 0 to 1000000 do
      v := B(134355);

    Writeln(Stop(startTime, stopTime, iCounterPerSec));

    Writeln('A:');

    Start(startTime);

    for I := 0 to 1000000 do
      v := A(134355);

    Writeln(Stop(startTime, stopTime, iCounterPerSec));

    Readln;

    exit;
  except
    on E: Exception do

    begin
      Writeln(E.ClassName, ': ', E.Message);
      Readln;
    end;
  end;

end.

...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471725
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чччДНяшик,

тут одни люди утверждают, что одно быстрее другого, а другие возражают. По факту - голословно, и те и другие.
Тесты и их результаты никто не представил.
Кто-то на исходники вайна ссылается, кто-то вообще на исходники непонятно чего, кто-то - на конкретную версию Windows.

Какой смысл спора, если есть одни лишь утверждения, но ни тестов, ни их результатов нет?

Забыл оптимизацию включить! Тогда в 1.7 %

B:
0.002759 сек.
A:
0.004741 сек.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471738
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Няшик,

Тут всё хитрее. Сделал простейшее приложение:
автор
Код: pascal
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.
program testcopy;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  WinAPI.Windows,
  System.SysUtils;

var
  Time: Cardinal;
begin
  try
    if ParamCount = 0 then
      raise Exception.Create('Usage: testcopy.exe "filename"');
    Time := GetTickCount;
    CopyFile(PChar(ParamStr(1)), PChar('.\' + ExtractFileName(ParamStr(1))), False);
    WriteLn('CopyFile: ', GetTickCount - Time, 'ms.');
    Time := GetTickCount;
    CopyFileEx(PChar(ParamStr(1)), PChar('.\' + ExtractFileName(ParamStr(1))), nil, nil, nil, 0);
    WriteLn('CopyFileEx: ', GetTickCount - Time, 'ms.');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  ReadLn;
end.



Дома в локалке при копировании по сети с ноутбука - разница в пределах погрешности. Win 10 1703.
На работе же у меня, то же самое приложение при копировании файла с файл-сервера показывало стабильную разницу в 15-20% в пользу CopyFile, причём при неоднократном запуске. Win 10 предыдущего релиза и комп на базе Core2Duo.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471740
misha mike
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpНа работе же у меня, то же самое приложение при копировании файла с файл-сервера показывало стабильную разницу в 15-20% в пользу CopyFile, причём при неоднократном запуске. Win 10 предыдущего релиза и комп на базе Core2Duo.
Зашибись. На параллельно нагруженном сервере в непонятно каких условиях что-то сработало быстрее.

Вы не находите, что эта аргументация как-то слабо канает против объективной реальности, представленной кодом, который совершенно очевиден и к тому же как минимум 17 лет не менялся?
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471742
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тогда уж надо, для чистоты эксперимента, дефрагментировать диск-приемник, запустить CopyFile, замерить время, удалить полученную копию, перезагрузиться, запустить CopyFileEx, замерить время....и так несколько раз. Потом посчитать мат. ожидание, дисперсию, выкинуть из эксперимента "плохие" значения и тогда уже делать выводы)))
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471743
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpНяшик,

Тут всё хитрее. Сделал простейшее приложение:
автор
Код: pascal
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.
program testcopy;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  WinAPI.Windows,
  System.SysUtils;

var
  Time: Cardinal;
begin
  try
    if ParamCount = 0 then
      raise Exception.Create('Usage: testcopy.exe "filename"');
    Time := GetTickCount;
    CopyFile(PChar(ParamStr(1)), PChar('.\' + ExtractFileName(ParamStr(1))), False);
    WriteLn('CopyFile: ', GetTickCount - Time, 'ms.');
    Time := GetTickCount;
    CopyFileEx(PChar(ParamStr(1)), PChar('.\' + ExtractFileName(ParamStr(1))), nil, nil, nil, 0);
    WriteLn('CopyFileEx: ', GetTickCount - Time, 'ms.');
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  ReadLn;
end.



Дома в локалке при копировании по сети с ноутбука - разница в пределах погрешности. Win 10 1703.
На работе же у меня, то же самое приложение при копировании файла с файл-сервера показывало стабильную разницу в 15-20% в пользу CopyFile, причём при неоднократном запуске. Win 10 предыдущего релиза и комп на базе Core2Duo.


Ахахахах)) Ахахахах ХХАХАХАХххахахахаах)) Ой)) Я не могу)) Я под столом!! Ужасс - то какой...

Теперь понятно чего это у него вторая функция быстрее))) !!!!
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471745
Barmaley57
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НяшикТеперь понятно чего это у него вторая функция быстрее))) !!!!Пост то читал? Там написано, что быстрее первая. Так что причины такой радости не ясны...
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471746
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У него 2-я типа медленней.

Что в общем тоже понятно почему может быть. :)

Например:
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471748
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Barmaley57НяшикТеперь понятно чего это у него вторая функция быстрее))) !!!!Пост то читал? Там написано, что быстрее первая. Так что причины такой радости не ясны...

Да какая разница - то ??? Он использует GetTickCount который живёт своей жизнью!
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471749
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну я надеюсь он более-менее адекватен, и подбирал файлы достаточного размера.
...
Рейтинг: 0 / 0
Как правильно "прибить" копирующий поток?
    #39471750
Няшик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatНу я надеюсь он более-менее адекватен, и подбирал файлы достаточного размера.

Ну если они будут мерить такими не точными способами, то у них вряд - ли получится точно замерить.
...
Рейтинг: 0 / 0
25 сообщений из 61, страница 2 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как правильно "прибить" копирующий поток?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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