-
Notifications
You must be signed in to change notification settings - Fork 0
/
UnitSorter.pas
136 lines (115 loc) · 3.59 KB
/
UnitSorter.pas
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
unit UnitSorter;
interface
uses
Windows, SysUtils, Classes,
Common, UnitBlockSorter, UnitMerger, UnitMemoryManager, UnitThreadManager;
procedure InitSort;
procedure SortData(const InFileName, OutFileName: string);
function GetMaxSortMemoryUsage: integer;
function GetMaxMergeMemoryUsage: integer;
implementation
uses
UnitSplitter, UnitBlockList;
var
ConsoleX, ConsoleY: integer;
CurPercent: integer;
MaxThreadRunning: integer = 0;
MaxSortMemoryUsage : integer = 0;
MaxMergeMemoryUsage: integer = 0;
function GetMaxSortMemoryUsage: integer;
begin
Result := MaxSortMemoryUsage;
end;
function GetMaxMergeMemoryUsage: integer;
begin
Result := MaxMergeMemoryUsage;
end;
function Max(const a, b: integer): integer;
begin
Result := a;
if b > a then
Result := b;
end;
procedure OnProgress(const Percent: Double);
var
ThreadRunning, NewPercent: integer;
begin
if Debug then
Exit;
NewPercent := trunc(Percent * 100000);
if NewPercent > CurPercent then
begin
CurPercent := NewPercent;
if not Debug then
SetConsoleCursorPos(ConsoleX, ConsoleY);
write(Format('%d.%.3d%%', [CurPercent div 1000, CurPercent mod 1000]));
if TrackMemoryUsage then
begin
ThreadRunning := ThreadManager.Running;
if ThreadRunning > MaxThreadRunning then
MaxThreadRunning := ThreadRunning;
if not Debug then
write(Format(' (%5d KB of heap is in use, %5d KB max, %2d threads running, %2d max)',
[GetMemoryUsage div 1024,
Max(MaxSortMemoryUsage, GetMaxMemoryUsage) div 1024,
ThreadRunning,
MaxThreadRunning]));
end;
end;
end;
const
WRITE_BUFFER_RATIO = 3; // áóôåð íà çàïèñü ïðè ñëèÿíèè âî WRITE_BUFFER_RATIO ðàç áîëüøå áóôåðà ñëèÿíèÿ
procedure InitSort;
var
MaxMem: integer;
begin
// Íàñòðîéêè ðàçìåðîâ áóôåðîâ
// Çäåñü íå ó÷èòûâàåòñÿ ðàçìåð ïàìÿòè, íóæíûé ïîä õðàíåíèå íîìåðîâ ñîçäàííûõ âðåìåííûõ ôàéëîâ (BlockList)
// ïðè áîëüøèõ ðàçìåðàõ ôàéëà îí èìååò çíà÷åíèå
MaxMem := MemoryAvailable * 1024;
SortBufferSize := MaxMem div (3 + 2 * MaxWorkerThreadCount);
MergeBufferSize := MaxMem div (1 + (2 + WRITE_BUFFER_RATIO) * MaxWorkerThreadCount);
MergeWriteBufferSize := MergeBufferSize * WRITE_BUFFER_RATIO;
end;
procedure SortData(const InFileName, OutFileName: string);
var
BlockCount: integer;
LastBlockFileName: string;
begin
Blocks := TBlockList.Create(InFileName); // ñïèñîê íîìåðîâ ñîçäàííûõ â ïðîöåññå ðàáîòû âðåìåííûõ ôàéëîâ
try
ThreadManager := TThreadManager.Create(MaxWorkerThreadCount);
try
GetConsoleCursorPos(ConsoleX, ConsoleY);
ShowConsoleCursor(false);
try
CurPercent := 0;
BlockCount := SplitFileIntoSortedBlocks(InFileName, ThreadManager, OnProgress);
MaxSortMemoryUsage := GetMaxMemoryUsage;
ResetMaxMemoryUsage;
if BlockCount > 0 then // BlockCount = 0 ==> îøèáêà ïðè ðàçáèåíèè (í-ð, íå ñìîãëè îòêðûòü âõîäíîé ôàéë)
begin
LastBlockFileName := MergeBlocks(OnProgress);
MaxMergeMemoryUsage := GetMaxMemoryUsage;
ThreadManager.WaitAllThreads;
if FileExists(OutFileName) then
DeleteFile(OutFileName);
if Debug then
CopyFile(PChar(LastBlockFileName), PChar(OutFileName), false)
else
RenameFile(LastBlockFileName, OutFileName);
end;
SetConsoleCursorPos(ConsoleX, ConsoleY);
write(StringOfChar(' ', 50));
SetConsoleCursorPos(ConsoleX, ConsoleY);
finally
ShowConsoleCursor(true);
end;
finally
ThreadManager.Free;
end;
finally
Blocks.Free;
end;
end;
end.