|
Benchmarks need to be treated with care, since they use to measure only what the user wants it to measure. Counting internet-databases the engine comes off well because of the very direct access to the database itself.
Further down this article you will find a small benchmark program that measured the performance of the server this website is running on (Duron 700, Linux 2.2.16):
|
tdbengine: system performance
00:00:07.89 Fill_String_Fields
00:00:05.76 Fill_Number_Fields
00:00:01.35 Create_DataBase
00:00:00.33 Create_Index
00:00:00.77 FindIn_Index
00:00:01.02 FindIn_Index_And_Read
00:00:04.97 Create_Fulltext_Index
00:00:05.95 Find_Fulltext_Index |
The first result points out, that the tdbengine is not really fast regarding string-operations. Here a field is filled with 40,000 random strings. But PERL
will also have Problems with this operation, because both systems have a neat, dynamic string-management.
The second result stands for another 40,000 random-strings which only consist of figures (right-of-point and left-of-point parts of a fixed point number),
subsequently the numbers are converted into the internal ansi-double-format. Since the random strings are a bit shorter here the execution time is some
shorter also, because the internal number procession is quite fast.
The third result is the time in which the associated database is created. So the benchmark created 10,000 records each with 4 alphanumeric and with 4 numeric fields. Here's the exact structure:
[STRUCTURE]
field_1=field_string_1,STRING,40
field_2=field_string_2,STRING,20
field_3=field_string_3,STRING,10
field_4=field_string_4,STRING,5
field_5=field_number_1,NUMBER,8,2
field_6=field_number_2,NUMBER,8,2
field_7=field_number_3,NUMBER,8,0
field_8=field_number_4,NUMBER,8,0 |
The fourth figure shows the time necessary to create a normal (=BTree) hierarchical index over the first two columns.
The fifth figure shows the time necessary for a simulated search over the previously created index. All 10,000 records are queried. The results are quite impressive.
The sixth figure additionally includes the time for reading the records. Again, all 10,000 records are queried and read.
The seventh figure shows the time necessary to create a complete fulltextindex inclusive fieldinformation.
Finally the last figure shows the time for a simulated field-based fulltext-query. Therefore, in the first numeric field 100 queries are carried out with
following search-pattern: '00*', '01*', ... '99*'. Finally in doing so all records are found. Every single query returns about 100 hits. This shows the
particular virtues of tdbengine.
And here is the program:
MODULE Benchmark
VAR String_Fields : STRING[,]
VAR Number_Fields : REAL[,]
VAR LegalChars : STRING
VAR Max : INTEGER = 10000
PROCEDURE RandomString(Length : INTEGER) : STRING
VAR result : STRING
VAR i : INTEGER
NLoop(i,Length-1,result:=result+LegalChars[1+random(system.length(LegalChars))])
RETURN result
ENDPROC
PROCEDURE RandomNumber(p1, p2 : INTEGER) : REAL
VAR s_result, t_result : STRING
VAR r_result : REAL
s_result:=RandomString(p1)
IF p2>0 THEN s_result:=s_result+'.'+RandomString(p2) END
r_result:=Val(s_result)
RETURN r_result
ENDPROC
PROCEDURE Fill_String_Fields : REAL
VAR i : INTEGER
VAR Now : REAL = system.now
LegalChars:='abcdefghijklmnopqrstuvwxyzäöüß'
NLoop(i,Max,String_Fields[i,0]:=RandomString(40))
NLoop(i,Max,String_Fields[i,1]:=RandomString(20))
NLoop(i,Max,String_Fields[i,2]:=RandomString(10))
NLoop(i,Max,String_Fields[i,3]:=RandomString(05))
RETURN system.now-Now
ENDPROC
PROCEDURE Fill_Number_Fields : REAL
VAR i : INTEGER
VAR Now : REAL = system.now
LegalChars:='0123456789'
NLoop(i,Max,Number_Fields[i,0]:=RandomNumber(10,2))
NLoop(i,Max,Number_Fields[i,1]:=RandomNumber(05,2))
NLoop(i,Max,Number_Fields[i,2]:=RandomNumber(10,0))
NLoop(i,Max,Number_Fields[i,3]:=RandomNumber(05,0))
RETURN system.now-Now
ENDPROC
PROCEDURE Create_DataBase : REAL
VAR i, j, database, db_def, db_dat, x : INTEGER
VAR Now : REAL = system.now
VAR db_name : STRING
db_def:=Rewrite('Ramtext')
WriteLn(db_def,'[STRUCTURE]')
WriteLn(db_def,'field_1=field_string_1,STRING,40')
WriteLn(db_def,'field_2=field_string_2,STRING,20')
WriteLn(db_def,'field_3=field_string_3,STRING,10')
WriteLn(db_def,'field_4=field_string_4,STRING,05')
WriteLn(db_def,'field_5=field_number_1,NUMBER,8,2')
WriteLn(db_def,'field_6=field_number_2,NUMBER,8,2')
WriteLn(db_def,'field_7=field_number_3,NUMBER,8,0')
WriteLn(db_def,'field_8=field_number_4,NUMBER,8,0')
Close(db_def)
MakeDir('benchmark')
db_name:='benchmark/benchmark.dat'
DelFile(db_name)
MakeDB(db_name,'',0,'Ramtext')
db_dat:=OpenDB(db_name,'',0,15)
i:=0
WHILE i++<=Max
ReadRec(db_dat,0)
NLoop(j,3,SetField(db_dat,j+1,String_Fields[i,j]))
NLoop(j,3,SetRField(db_dat,j+5,Number_Fields[i,j]))
x:=WriteRec(db_dat,FileSize(db_dat)+1)
END
CloseDB(db_dat)
RETURN system.now-Now
ENDPROC
PROCEDURE Create_Index : REAL
VAR Now : REAL = system.now
VAR db_dat : INTEGER
VAR db_name : STRING
db_name:='benchmark/benchmark.dat'
DelFile('benchmark/bm.ind')
db_dat:=OpenDB(db_name,'',0,15)
GenIndex(db_dat,'$1,$2','bm.ind')
CloseDB(db_dat)
RETURN system.now-Now
ENDPROC
PROCEDURE FindIn_Index : REAL
VAR Now : REAL = system.now
VAR db_dat, i, x : INTEGER
VAR db_name : STRING = 'benchmark/benchmark.dat'
db_dat:=OpenDB(db_name,'',0,0)
WHILE i++<=FileSize(db_dat)
x:=FindRec(db_dat,String_Fields[i,0]+','+String_Fields[i,1],'bm.ind',1)
IF x=0 THEN CGIWriteLn('index_error') END
END
CloseDB(db_dat)
RETURN system.now-Now
ENDPROC
PROCEDURE FindIn_Index_And_Read : REAL
VAR Now : REAL = system.now
VAR db_dat, i, x : INTEGER
VAR db_name : STRING = 'benchmark/benchmark.dat'
db_dat:=OpenDB(db_name,'',0,0)
WHILE i++<=FileSize(db_dat)
x:=FindRec(db_dat,String_Fields[i,0]+','+String_Fields[i,1],'bm.ind',1)
IF x=0 THEN CGIWriteLn('index_error') ELSE ReadRec(db_dat,x) END
END
CloseDB(db_dat)
RETURN system.now - Now
ENDPROC
PROCEDURE Create_Fulltext_Index : REAL
VAR Now : REAL = system.now
VAR db_dat, index_dat, rel_dat, x : INTEGER
VAR db_name, index_name, rel_name : STRING
db_name:='benchmark/benchmark.dat'
index_name:='benchmark/index.dat'
rel_name:='benchmark/index.rel'
DelFile(index_name)
DelFile(rel_name)
GenList(index_name)
GenRel('benchmark','index',rel_name)
db_dat:=OpenDB(db_name,'',0,0)
index_dat:=OpenDB(index_name,'',0,15)
rel_dat:=OpenDB(rel_name,'',0,15)
x:=ScanRecs(db_dat,index_dat,rel_dat,Fields("COMPLETE"))
CloseDB(rel_dat)
CloseDB(index_dat)
CloseDB(db_dat)
RETURN system.now-Now
ENDPROC
PROCEDURE Find_Fulltext_Index : REAL
VAR Now : REAL = system.now
VAR db_dat, index_dat, rel_dat, x, i, j : INTEGER
VAR db_name, index_name, rel_name, searchstr : STRING
db_name:='benchmark/benchmark.dat'
index_name:='benchmark/index.dat'
rel_name:='benchmark/index.rel'
db_dat:=OpenDB(db_name,'',0,0)
index_dat:=OpenDB(index_name,'',0,0)
rel_dat:=OpenDB(rel_name,'',0,0)
WHILE i<10 DO
j:=0
WHILE j<10 DO
searchstr:='field_number_1:'+str(i)+str(j)+'*'
x:=x+MarkTable(db_dat,index_dat,searchstr,'0123456789','',0,rel_dat)
j++
END
i++
END
IF x<>Max THEN CGIWriteLn('fulltext_index_error') END
CloseDB(rel_dat)
CloseDB(index_dat)
CloseDB(db_dat)
RETURN system.now-Now
ENDPROC
PROCEDURE Main
CGIWriteLn('content-type: text/plain')
CGIWriteLn('')
CGIWriteLn('tdbengine: system performance')
CGIWriteLn('')
InitArray(String_Fields[Max,3]); InitArray(Number_Fields[Max,3]);
CGIWriteLn(TimeStr(Fill_String_Fields,2)+''+'Fill_String_Fields')
CGIWriteLn(TimeStr(Fill_Number_Fields,2)+''+'Fill_Number_Fields')
CGIWriteLn(TimeStr(Create_DataBase,2)+''+'Create_DataBase')
CGIWriteLn(TimeStr(Create_Index,2)+''+'Create_Index')
CGIWriteLn(TimeStr(FindIn_Index,2)+''+'FindIn_Index')
CGIWriteLn(TimeStr(FindIn_Index_And_Read,2)+''+'FindIn_Index_And_Read')
CGIWriteLn(TimeStr(Create_Fulltext_Index,2)+''+'Create_Fulltext_Index')
CGIWriteLn(TimeStr(Find_Fulltext_Index,2)+''+'Find_Fulltext_Index')
ENDPROC
Once again, now the results in a table:
| Fill_String_Fields |
00:00:07.89 |
Creation of a string-array with 40,000 random strings, each 10,000 with lengths 40, 20, 10 and 5. |
| Fill_Number_Fields |
00:00:05.76 |
Creation of a real-array with 40,000 random numbers, each 10,000 with 12 digits (with 2 of them right of the separator), 10 digits as integer, 7 digits (with 2 of them right of the separator) and 5 digits as integer. The numbers are generated from random strings. |
| Create_DataBase |
00:00:01.35 |
Creation of a database from the previously generated string- and numberfields. The database consists of 10,000 records with 8 columns each. |
| Create_Index |
00:00:00.33 |
Creation of a hierarchical index over the just created database. The first two fields get indexed. |
| FindIn_Index |
00:00:00.77 |
All 10,000 records are queried (and found) using the index. |
| FindIn_Index_And_Read |
00:00:01.02 |
All 10,000 records are queried using the index and additionally read in the database. |
| Create_Fulltext_Index |
00:00:04.97 |
Creation of a (field-based) fulltext-index over all fields (columns) of the database. |
| Find_Fulltext_Index |
00:00:05.95 |
100 fulltext-queries in the first column of the table. Each search returns an average of 100 hits. All records are found. |
|