Skip to content

Commit 74cf3bb

Browse files
committed
- Delphi version tested under Windows
1 parent 5593525 commit 74cf3bb

File tree

6 files changed

+1575
-98
lines changed

6 files changed

+1575
-98
lines changed

generator/Common/generate.common.pas

Lines changed: 112 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
unit Generate.Common;
22

3+
{$IFDEF FPC}
34
{$mode ObjFPC}{$H+}
5+
{$ENDIF}
46

57
interface
68

79
uses
8-
Classes
9-
, SysUtils
10-
, streamex
11-
;
10+
Classes, SysUtils, Math
11+
{$IFDEF FPC}
12+
, streamex, bufstream
13+
{$ELSE}
14+
, System.Diagnostics
15+
{$ENDIF}
16+
;
1217

1318
const
1419
cSeed: LongInt = 46668267; // '1BRC' in ASCII
1520
cColdestTemp = -99.9;
1621
cHottestTemp = 99.9;
22+
cLineBreak = #13#10;
1723

1824
type
19-
{ TGenerator }
25+
{ TGenerator }
2026
TGenerator = class(TObject)
2127
private
2228
FInputFile: String;
@@ -25,10 +31,8 @@ TGenerator = class(TObject)
2531
FStationNames: TStringList;
2632

2733
procedure BuildStationNames;
28-
function GenerateProgressBar(
29-
APBPosition, APBMax, APBWIdth, AFileSize:Int64;
30-
ATimeElapsed: TDateTime
31-
):String;
34+
function GenerateProgressBar(APBPosition, APBMax, APBWIdth, AFileSize: Int64;
35+
ATimeElapsed: TDateTime): String;
3236
protected
3337
public
3438
constructor Create(AInputFile, AOutputFile: String; ALineCount: Int64);
@@ -38,34 +42,31 @@ TGenerator = class(TObject)
3842
published
3943
end;
4044

41-
implementation
45+
{$IFNDEF FPC}
4246

43-
uses
44-
Math,
45-
bufstream
46-
;
47+
TStringArray = array of string;
48+
TWriteBufStream = TFileStream;
49+
{$ENDIF}
50+
51+
implementation
4752

4853
const
4954
batchPercent = 10;
5055

51-
{ TGenerator }
56+
{ TGenerator }
5257

53-
constructor TGenerator.Create(
54-
AInputFile,
55-
AOutputFile: String;
56-
ALineCount: Int64
57-
);
58+
constructor TGenerator.Create(AInputFile, AOutputFile: String; ALineCount: Int64);
5859
begin
59-
FInputFile:= AInputFile;
60-
FOutPutFile:= AOutputFile;
61-
FLineCount:= ALineCount;
62-
63-
FStationNames:= TStringList.Create;
64-
FStationNames.Capacity:= 50000;
65-
//FStationNames.CaseSensitive:= False;
66-
FStationNames.UseLocale:= False;
67-
FStationNames.Duplicates:= dupIgnore;
68-
FStationNames.Sorted:= True;
60+
FInputFile := AInputFile;
61+
FOutPutFile := AOutputFile;
62+
FLineCount := ALineCount;
63+
64+
FStationNames := TStringList.Create;
65+
FStationNames.Capacity := 50000;
66+
// FStationNames.CaseSensitive:= False;
67+
FStationNames.UseLocale := False;
68+
FStationNames.Duplicates := dupIgnore;
69+
FStationNames.Sorted := True;
6970
end;
7071

7172
destructor TGenerator.Destroy;
@@ -79,30 +80,46 @@ procedure TGenerator.BuildStationNames;
7980
inputStream: TFileStream;
8081
streamReader: TStreamReader;
8182
entry: String;
82-
count: Int64 = 0;
83-
start, stop: QWord;
83+
count: Int64;
84+
start, stop: {$IFDEF FPC}QWord{$ELSE}Int64{$ENDIF};
8485
begin
8586
WriteLn('Building Weather Stations...');
8687
// Load the Weather Station names
8788
if FileExists(FInputFile) then
8889
begin
89-
inputStream:= TFileStream.Create(FInputFile, fmOpenRead);
90+
inputStream := TFileStream.Create(FInputFile, fmOpenRead);
9091
try
91-
streamReader:= TStreamReader.Create(inputStream);
92+
streamReader := TStreamReader.Create(inputStream);
9293
try
93-
start:= GetTickCount64;
94+
{$IFDEF FPC}
95+
start := GetTickCount64;
9496
while not streamReader.Eof do
9597
begin
96-
entry:= streamReader.ReadLine;
98+
entry := streamReader.ReadLine;
9799
if entry[1] <> '#' then
98100
begin
99-
entry:= entry.Split(';')[0];
101+
entry := entry.Split(';')[0];
100102
FStationNames.Add(entry);
101-
//WriteLn('Got: ', entry);
103+
// WriteLn('Got: ', entry);
102104
Inc(count);
103105
end;
104106
end;
105-
stop:= GetTickCount64;
107+
stop := GetTickCount64;
108+
{$ELSE}
109+
start := TStopwatch.GetTimeStamp;
110+
while not streamReader.EndOfStream do
111+
begin
112+
entry := streamReader.ReadLine;
113+
if entry[1] <> '#' then
114+
begin
115+
entry := entry.Split([';'])[0];
116+
FStationNames.Add(entry);
117+
// WriteLn('Got: ', entry);
118+
Inc(count);
119+
end;
120+
end;
121+
stop := TStopwatch.GetTimeStamp;
122+
{$ENDIF}
106123
finally
107124
streamReader.Free;
108125
end;
@@ -112,35 +129,29 @@ procedure TGenerator.BuildStationNames;
112129
end
113130
else
114131
begin
115-
raise Exception.Create(Format('File "%s" not found.', [ FInputFile ]));
132+
raise Exception.Create(Format('File "%s" not found.', [FInputFile]));
116133
end;
117-
WriteLn(Format('Done: Processed %.n entries from a total of %.n weather stations in %d ms', [
118-
Double(count),
119-
Double(FStationNames.Count),
120-
stop-start
121-
]));
134+
WriteLn(Format
135+
('Done: Processed %.n entries from a total of %.n weather stations in %d ms',
136+
[Double(count), Double(FStationNames.count), stop - start]));
122137
WriteLn;
123138
end;
124139

125-
function TGenerator.GenerateProgressBar(
126-
APBPosition, APBMax, APBWIdth, AFileSize: Int64;
127-
ATimeElapsed: TDateTime
128-
): String;
140+
function TGenerator.GenerateProgressBar(APBPosition, APBMax, APBWIdth, AFileSize: Int64;
141+
ATimeElapsed: TDateTime): String;
129142
var
130143
percentDone: Double;
131144
filled: Integer;
132145
begin
133-
percentDone:= (100 * APBPosition) / APBMax;
134-
filled:= (APBWIdth * APBPosition ) div APBMax;
135-
Result:= '[';
136-
Result:= Result + StringOfChar('#', filled);
137-
Result:= Result + StringOfChar('-', APBWIdth - filled);
138-
Result:= Result + Format('] %5.2f %%', [ percentDone ]);
139-
Result:= Result + Format(' lines: %.n, file size: %.n, elapsed: %s ', [
140-
Double(APBPosition),
141-
Double(AFileSize),
142-
FormatDateTime('n" min, "s" sec"', ATimeElapsed)
143-
]);
146+
percentDone := (100 * APBPosition) / APBMax;
147+
filled := (APBWIdth * APBPosition) div APBMax;
148+
Result := '[';
149+
Result := Result + StringOfChar('#', filled);
150+
Result := Result + StringOfChar('-', APBWIdth - filled);
151+
Result := Result + Format('] %5.2f %%', [percentDone]);
152+
Result := Result + Format(' lines: %.n, file size: %.n, elapsed: %s ',
153+
[Double(APBPosition), Double(AFileSize), FormatDateTime('n" min, "s" sec"',
154+
ATimeElapsed)]);
144155
end;
145156

146157
procedure TGenerator.Generate;
@@ -158,18 +169,18 @@ procedure TGenerator.Generate;
158169
begin
159170
// Randomize sets this variable depending on the current time
160171
// We just set it to our own value
161-
RandSeed:= cSeed;
172+
RandSeed := cSeed;
162173

163174
// Build list of station names
164175
BuildStationNames;
165176

166-
outputFileStream:= TFileStream.Create(FOutPutFile, fmCreate);
177+
outputFileStream := TFileStream.Create(FOutPutFile, fmCreate);
167178

168-
progressBatch:= floor(FLineCount * (batchPercent / 100));
169-
start:= Now;
179+
progressBatch := floor(FLineCount * (batchPercent / 100));
180+
start := Now;
170181

171-
//based on code @domasz from lazarus forum, github: PascalVault
172-
stationsCount := FStationNames.Count;
182+
// based on code @domasz from lazarus forum, github: PascalVault
183+
stationsCount := FStationNames.count;
173184
SetLength(stationArray, stationsCount);
174185
for i := 0 to stationsCount - 1 do
175186
stationArray[i] := FStationNames[i];
@@ -181,10 +192,15 @@ procedure TGenerator.Generate;
181192
begin
182193
randomTempStr := IntToStr(i);
183194
case Ord(randomTempStr[0]) of
184-
1: randomTempFinal := '0.' + randomTempStr;
185-
2: randomTempFinal := randomTempStr[1] + '.' + randomTempStr[2];
186-
3: randomTempFinal := randomTempStr[1] + randomTempStr[2] + '.' + randomTempStr[3];
187-
4: randomTempFinal := randomTempStr[1] + randomTempStr[2] + randomTempStr[3] + '.' + randomTempStr[4];
195+
1:
196+
randomTempFinal := '0.' + randomTempStr;
197+
2:
198+
randomTempFinal := randomTempStr[1] + '.' + randomTempStr[2];
199+
3:
200+
randomTempFinal := randomTempStr[1] + randomTempStr[2] + '.' + randomTempStr[3];
201+
4:
202+
randomTempFinal := randomTempStr[1] + randomTempStr[2] + randomTempStr[3] + '.' +
203+
randomTempStr[4];
188204
end;
189205
temperatureArray[i * 2 - 1] := randomTempFinal;
190206
temperatureArray[i * 2] := '-' + randomTempFinal;
@@ -194,55 +210,60 @@ procedure TGenerator.Generate;
194210
line := '';
195211

196212
try
197-
//outputBufWriter:= TWriteBufStream.Create(outputFileStream, 4*1024);
198-
outputBufWriter:= TWriteBufStream.Create(outputFileStream, 64*1024);
213+
// outputBufWriter:= TWriteBufStream.Create(outputFileStream, 4*1024);
214+
{$IFDEF FPC}
215+
outputBufWriter := TWriteBufStream.Create(outputFileStream, 64 * 1024);
216+
{$ENDIF}
199217
try
200-
Write(GenerateProgressBar(1, FLineCount, 50, 0, Now - start), #13);
218+
Write(GenerateProgressBar(1, FLineCount, 50, 0, Now - start), cLineBreak);
201219
// Generate the file
202-
for index:= 1 to FLineCount do
220+
for index := 1 to FLineCount do
203221
begin
204-
stationId:= Random(stationsCount);
222+
stationId := Random(stationsCount);
205223
// This is all paweld magic:
206224
// From here
207-
randomTemp:= Random(temperaturesCount);
208-
line := line + stationArray[stationId] + ';' + temperatureArray[randomTemp] + #13#10;
209-
//Write(line);
225+
randomTemp := Random(temperaturesCount);
226+
line := line + stationArray[stationId] + ';' + temperatureArray[randomTemp] +
227+
cLineBreak;
228+
// Write(line);
210229
if index mod 10000 = 0 then
211230
begin
231+
{$IFNDEF FPC}
232+
outputFileStream.WriteBuffer(line[1], Length(line));
233+
{$ELSE}
212234
outputBufWriter.WriteBuffer(line[1], Length(line));
235+
{$ENDIF}
213236
line := '';
214237
end;
215238
// To here
216239
Dec(progressBatch);
217240
if progressBatch = 0 then
218241
begin
219-
Write(GenerateProgressBar(
220-
index,
221-
FLineCount,
222-
50,
223-
outputFileStream.Size,
224-
Now - start
225-
), #13);
226-
progressBatch:= floor(FLineCount * (batchPercent / 100));
242+
Write(GenerateProgressBar(index, FLineCount, 50, outputFileStream.Size,
243+
Now - start), cLineBreak);
244+
progressBatch := floor(FLineCount * (batchPercent / 100));
227245
end;
228246
end;
229247
if line <> '' then
230248
begin
249+
{$IFNDEF FPC}
250+
outputFileStream.WriteBuffer(line[1], Length(line));
251+
{$ELSE}
231252
outputBufWriter.WriteBuffer(line[1], Length(line));
253+
{$ENDIF}
232254
end;
233255
finally
256+
{$IFDEF FPC}
234257
outputBufWriter.Free;
258+
{$ENDIF}
235259
end;
236260
finally
237261
WriteLn;
238262
WriteLn;
239-
WriteLn(Format('Done: file size: %.n, elapsed: %s', [
240-
Double(outputFileStream.Size),
241-
FormatDateTime('n" min, "s" sec"', Now - start)
242-
]));
263+
WriteLn(Format('Done: file size: %.n, elapsed: %s', [Double(outputFileStream.Size),
264+
FormatDateTime('n" min, "s" sec"', Now - start)]));
243265
outputFileStream.Free;
244266
end;
245267
end;
246268

247269
end.
248-

generator/Common/generate.console.pas

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
unit Generate.Console;
22

3+
{$IFDEF FPC}
34
{$mode ObjFPC}{$H+}
5+
{$ENDIF}
46

57
interface
68

@@ -18,9 +20,11 @@ interface
1820
cLongOptInput = 'input-file';
1921
cShortOptOutput: Char = 'o';
2022
cLongOptOutput = 'output-file';
21-
cShortOptNumner: Char = 'n';
23+
cShortOptNumber: Char = 'n';
2224
cLongOptNumber = 'line-count';
23-
25+
cShortOptions: array of char = ['h', 'v', 'i', 'o', 'n'];
26+
cLongOptions: array of string = ['help', 'version', 'input-file', 'output-file',
27+
'line-count'];
2428

2529
resourcestring
2630
rsAppTitle = 'One Billion Row Challenge Generator';

generator/Common/version.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
'0.3'
1+
const
2+
cVersion = '0.3';

0 commit comments

Comments
 (0)