2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Простое любопытство. Delphi и Masm
Сообщение11.03.2009, 03:44 
Здравствуйте. Написал 2 программы, вроде по алгоритму работы одинаковые, только для делфи использовал стандартные функции, а для ассемблера winAPI. Суть - заполнение текстового файлика заранее заданными символами (циклы я сделал одинаковые и большие (мне в принципе всеравно сколько выходной файл будет весить). Запускаю программу, написанную в делфи, за минуту работы получаю файл весом в 1700мб (чуть больше даже)... Запускаю программу написанную на ассемблере, за это же время файл весит меньше 700мб... В чем дело?... Есть подозрение, что функция WriteFile в ассемблере помимо всегоп прочего возвращает в переменную и количество записанных байт, что тормозит процесс заполнения. Так ли?.. А есть альтернатива этой функции....
Коды выложу тут...
Delphi:
Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
res:textFile;
i:integer;

begin
  AssignFile(res,'asd.asd');
  rewrite(res);
  write(res,'asdasdasdasdasdasdasdasd');
  closeFile(res);
  append(res);
  for i:=1 to 200000000 do begin

    write(res,'asdasdasdasdasdasdasdasd');

  end;
  closeFile(res);
end.


assembler
Код:
TITLE программа создания файла и записи в него строк (newfile.asm)
.386
.MODEL flat, stdcall
INCLUDE d:\0_assembler\mylib.inc
endl EQU <0Dh,0Ah>
.data
ConsoleOutHandle DWORD 0
MessageNew BYTE "asdasdasdasdasdasdasdasd"
MessageNewSize = ($ - MessageNew)
ErrorMsg BYTE "error read/write",endl
ErrorMsgSize = ($ - ErrorMsg)
fileName BYTE "wow.be",0
fileHandle DWORD ?
FileTextBuffer DWORD ?
BytesWritten DWORD ?
.code
main PROC
   INVOKE CreateFileA,
      OFFSET fileName,
      GENERIC_WRITE,   
      DO_NOT_SHARE,
      0,
      OPEN_ALWAYS,   
      FILE_ATTRIBUTE_NORMAL,
      0
      mov fileHandle,EAX
      .IF EAX == INVALID_HANDLE_VALUE
         PUSHAD
         INVOKE GetStdHandle,STD_OUTPUT_HANDLE
            mov ConsoleOutHandle,EAX
         POPAD
         PUSHAD
         MOV EDX,OFFSET ErrorMsg
         INVOKE WriteConsoleA,
            ConsoleOutHandle,
            OFFSET ErrorMsg,
            ErrorMsgSize,
            OFFSET BytesWritten,
            0
         POPAD
         INVOKE WaitMsg
      JMP QuitNow
      .ENDIF
   MOV ECX,0BEBC200h
   start:
   INVOKE WriteFile,
      fileHandle,
      OFFSET MessageNew,
      MessageNewSize,
      OFFSET FileTextBuffer,
      0
   LOOP start
   INVOKE CloseHandle,fileHandle
   INVOKE WaitMsg
QuitNow:
   INVOKE ExitProcess,0
main ENDP
END main


в mylib.inc идет только описание констант и функций... Заранее спасибо:)

 
 
 
 
Сообщение11.03.2009, 13:20 
Аватара пользователя
Процедура Write в Delphi записывает данные на диск не сразу, а предварительно кэширует их (объём буфера --- 128 байт), и пишет на диск (вызывает функцию WinAPI WriteFile()) только тогда, когда буфер заполнится.
Поэтому программа на Delphi вызывает функцию WriteFile() примерно в 5 раз (128/MessageNewSize) реже, чем ассемблерный вариант, соответственно, в 5 раз меньше времени уходит на накладные расходы (вход в режим ядра и выход из него), которые в данном случае больше, чем время, уходящее на собственно операцию записи (разумеется, ещё раз кэшированную уже на уровне ядра).

Мораль: для увеличения производительности операций ввода/вывода следует по возможности минимизировать число вызовов функций WinAPI, работающих в режиме ядра (за счёт дополнительного кэширования).

 
 
 
 
Сообщение11.03.2009, 14:38 
worm2
Спасибо за содержательный ответ. Попробую переделать.

 
 
 [ Сообщений: 3 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group