Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.12.18;
Скачать: CL | DM;

Вниз

Запись элементов очень большого масива в файл с макс скоростью   Найти похожие ветки 

 
Manufel ©   (2005-11-12 23:29) [0]

Задача такая, есть динамичный массив типа byte, содержащий большое(около 10^7) количество элементов, необходимо записать его в файл
Я реализовал это так:

type
 ByteArr=array of byte;
 ByteFile=file of byte;
.....
procedure WriteBytesToFile(var B:ByteArr;var F:ByteFile);
var i:int64;
begin
 assignfile(f,MainForm.savefile.Text);
 rewrite(f);
 i:=0;
 while i<length(B) do
 begin
   write(f,B[i]);
   inc(i);
 end;
 Closefile(f);
end;

Реализация самая простая какая приходит в голову, она работает но массив записывается около минуты, хотя 10^7 байт это около 10 Мб, а на моей машине файлы такого размера копируются за 1-2 сек

Отсюда вопрос, как можно реализовать более эфективно запись всего этого массива в файл? Возможно существует какаянибудь функция в которою передаётся указатель на начало массива и его размер, записывающая всё напрямую из указаного промежутка адресов в оперативной памяти на жёсткий диск? Или же какаянибудь другая эффективная реализация?
Очень прошу помочь!

P.S. Извиняюсь за возможно несколько некоректную формулировку, я 2 года не занимался програмированием, и к сожалению растерял большую часть знаний :(


 
Eraser ©   (2005-11-12 23:32) [1]


> Manufel ©   (12.11.05 23:29)

Используй TFileStream и пиши напрямую память в которой расположен массив. Несколько секунд займёт.


 
Manufel ©   (2005-11-13 03:02) [2]

Разобрался с TFileStream, теперь время 0,25-0,41 сек :)
Спасибо большое!


 
злобная танька   (2005-11-13 09:06) [3]

а что круче TFileStream или BlockWrite?


 
begin...end ©   (2005-11-13 09:11) [4]

> злобная танька   (13.11.05 09:06) [3]

Если имеется в виду критерий скорости, то примерно одинаково (при правильном использовании). И в первом, и во втором случае запись в файл сводится к вызову WriteFile (API).


 
TUser ©   (2005-11-13 10:17) [5]

Писать по 1 байту - это заведомо медленно.

program wf;
{$apptype console}
uses Classes, SysUtils, DateUtils;

type
TProcedure = procedure;

const Count = 10000000;
     FastCount = 512;

var Ar: array [0..Count-1] of byte;

procedure Test (P: TProcedure);
var t: TDateTime;
begin
  t:=now;
  P;
  writeln ("Tested: "+inttostr(MillisecondsBetween(t,now)));
end;

procedure Write2File;
var i: integer;
    f: file of byte;
begin
 assignfile(f,"test");
 rewrite(f);
 for i:=0 to Count-1 do
   write (f,Ar[i]);
 Closefile(f);
end;

procedure WriteFast;
var i, j: integer;
    f: file;
    b: array [0..FastCount-1] of byte;
begin
 assignfile(f,"test");
 rewrite(f,1);
 j:=0;
 for i:=0 to Count-1 do begin
   b[j]:=Ar[i];
   inc (j);
   if j = FastCount then begin
     BlockWrite (f,b[0],FastCount);
     j:=0;
     end;
   end;
 BlockWrite (f,b[0],j);
 Closefile(f);
end;

procedure Write2Stream;
var f: TStream;
begin
 f:=TFileStream.Create("test",fmOpenWrite);
 f.WriteBuffer(Ar[0],Count);
 f.Free;
end;

begin
 Test (Write2File);
 Test (WriteFast);
 Test (Write2Stream);
end.


H:\temp\wf>dcc32 wf.dpr
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
wf.dpr(64)
65 lines, 0.11 seconds, 72228 bytes code, 10003621 bytes data.

H:\temp\wf>wf
Tested: 34672
Tested: 391
Tested: 297

H:\temp\wf>fpc -Mdelphi -OG2p3 wf.dpr
Free Pascal Compiler version 2.0.0 [2005/05/08] for i386
Copyright (c) 1993-2005 by Florian Klaempfl
Target OS: Win32 for i386
Compiling wf.dpr
Linking wf.exe
63 Lines compiled, 1.1 sec

H:\temp\wf>wf
Tested: 35890
Tested: 454
Tested: 311


 
Leonid Troyanovsky ©   (2005-11-14 08:37) [6]


> Manufel ©   (12.11.05 23:29)
 
> Отсюда вопрос, как можно реализовать более эфективно запись
> всего этого массива в файл? Возможно существует какаянибудь
> функция в которою передаётся указатель на начало массива
> и его размер, записывающая всё напрямую из указаного промежутка
> адресов в оперативной памяти на жёсткий диск? Или же какаянибудь
> другая эффективная реализация?


RTFM: CreateFileMapping, MapViewOfFile & etc

--
Regards, LVT.


 
Anatoly Podgoretsky ©   (2005-11-14 08:55) [7]

Leonid Troyanovsky ©   (14.11.05 08:37) [6]
Будет ли быстрее именно для данного случая?


 
Anatoly Podgoretsky ©   (2005-11-14 08:57) [8]

Да и о какой скорости тут говорить, когда 10 мб копируется за доли секунды, нет предмета для борьбы.


 
Leonid Troyanovsky ©   (2005-11-14 09:18) [9]


> Anatoly Podgoretsky ©   (14.11.05 08:55) [7]
> Leonid Troyanovsky ©   (14.11.05 08:37) [6]
> Будет ли быстрее именно для данного случая?


Если только записывать, то, конечно, не будет.
А если нужно не только писать, но и читать, то будет эффективней.

--
Regards, LVT.


 
PAVIA ©   (2005-11-14 20:40) [10]

Запустил код TUsera
Borland Delphi Version 14.0
FastCount=512
Tested: 38562
Tested: 140
Tested: 812

увеличел FastCount=4096 размер одной страницы памяти. Дальнейшие увеличение не имеет смысла, что и подтвердили эксперементы.
Tested: 38577
Tested: 63
Tested: 671


 
Manufel ©   (2005-11-17 18:47) [11]

Спасибо конечно, но я же написал что уже со всем разобрался, с использованием TFileStream скорость чтения из файла+обработки+записи в файл, 60-80 Мб, это занимает 1,5-2 секунды, и такая скорость меня вполне устраивает, а 10Мб те и обсуждать не стоит =)


 
Verg ©   (2005-11-17 18:55) [12]

type
ByteArr=array of byte;
.....
procedure WriteBytesToFile(var B:ByteArr);
var f : file;
begin
assignfile(f,MainForm.savefile.Text);
rewrite(f, 1);
  BlockWrite(f, B[0], length(B) );
Closefile(f);
end;


Бывает быстрее?


 
Leonid Troyanovsky ©   (2005-11-17 19:07) [13]


> Verg ©   (17.11.05 18:55) [12]

> Бывает быстрее?


Конечно.
Скинь дельфийские одежды - и быстрее на пару .. тактов.

--
Regards, LVT.



Страницы: 1 вся ветка

Текущий архив: 2005.12.18;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.063 c
3-1130503241
Брат
2005-10-28 16:40
2005.12.18
Передача параметра


6-1126157400
JohnS
2005-09-08 09:30
2005.12.18
Indy + FTP


2-1132177838
Out
2005-11-17 00:50
2005.12.18
MIDAS


2-1133393751
Юрий Ж.
2005-12-01 02:35
2005.12.18
[?]TClientSocket &amp; TServerSocket


2-1133326401
BanderLog
2005-11-30 07:53
2005.12.18
Проблемы с VK_BACK