Форум: "Основная";
Текущий архив: 2005.12.18;
Скачать: [xml.tar.bz2];
ВнизЗапись элементов очень большого масива в файл с макс скоростью Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.013 c