Deutsch English
Blog
Home
Über tdbengine
Newsletter
Download
Helpware
Chat
Dokumentation
Einführungskurs
Befehlsreferenz
HOWTO - Wie kann ich...?
Projekte
Links
Benchmarks
Bug Reporting
Supportanfrage
 
Home    Überblick    Suche    Impressum    Kontakt    Mitglieder
Benchmarks
Benchmarks sind so eine Sache, meistens messen sie genau das, was man gerade messen will. Bei Internetdatenbanken schneidet die tdbengine aufgrund des ganz direkten Datenbankzugriffs in vielen Fällen sehr gut ab.

Im Anhang an dieses Artikels finden Sie ein kleines Benchmark-Programm, das auf einem Duron 700 mit Linux 2.2.16 folgende Ergebnisse liefert:

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

Die erste Zahl weist darauf hin, dass die tdbengine bei String-Operationen nicht unbedingt rasant ist. Hier wird ein Feld mit 40.000 Zufallsstrings gefüllt. Allerdings wird damit auch Perl seine Probleme haben, denn beide Systeme machen eine saubere dynamische String-Verwaltung.

Bei der zweiten Zahl werden ebenfalls 40.000 Zufallsstrings erzeugt, die allerdings nur aus Ziffern bestehen (Vor- und Nachkommateil einer Festkommazahl), anschließen werden die Zahlen in das interne Ansi-Double-Format konvertiert. Da die Zufallsstrings hier kürzer sind, ist auch die Ausführungszeit etwas geringer, denn die interne Zahlenverarbeitung ist recht flott.

Die dritte Zahl gibt die Zeit an, in der die zugehörige Datenbank erzeugt wird. Es werden also 10.000 Datensätze mit jeweils 4 alphanumerischen und 4 numerischen Datenfeldern erzeugt. Hier die genaue Struktur:

[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

Die vierte Zahl zeigt die Zeit für die Erzeugung eines normalen (=BTree) hierarchischen Index über die ersten beiden Spalten der Tabelle. Die fünfte Zahl zeigt die Zeit für eine simulierte Suche über den gerade erzeugten Index. Es werden alle 10.000 Datensätze gesucht. Das Ergebnis ist m.E. recht imponierend. Bei der sechsten Zahl kommt noch die Zeit für das Lesen der Datensätze hinzu. Es werden wiederum alle 10.000 Datensätze gesucht und gelesen. Die siebte Zahl gibt die Zeit für die Erzeugung eines kompletten Volltextindex mit Feldinformation an.
Die letzte Zahl schließlich gibt die Zeit für eine simulierte feldbezogene Volltext-Suche an. Dabei werden im ersten numerischen Feld 100 Suchen ausgeführt mit folgenden Suchmustern: '00*', '01*', ... '99*'. Dabei werden schließlich alle Datensätze gefunden. Jede einzelne Suche liefert im Schnitt 100 Treffer. Hier zeigt sich, wo die besonderen Stärken der tdbengine liegen.

Und hier ist das Programm:

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

Hier nochmal tabellarisch die Auswertung

Fill_String_Fields 00:00:07.89

Anlage eines String-Arrays mit 40.000 Zufallsstrings, jeweils 10.000 der Länge 40, 20, 10 und 5

Fill_Number_Fields 00:00:05.76

Anlage eines Real-Arrays mit 40.000 Zufallszahlen, jeweils 10.000 mit 12 Ziffern mit zwei Nachkommastellen, 10 Ziffern ohne Nachkommastelle, 7 Zifffern mit zwei Nachkommastellen und 5 Ziffern ohne Nachkommastelle. Sie Zahlen werden aus Zufallsstrings gewonnen.

Create_DataBase 00:00:01.35

Anlage einer Datenbank aus den zuvor generierten String- und Zahlenfeldern.Die Datenbank besteht aus einer Tabelle mit 10.000 Zeilen zu je 8 Spalten.

Create_Index 00:00:00.33

Anlage eines hierarchischen Index über die soeben generierte Datenbank. Indiziert weden die ersten beiden Felder.

FindIn_Index 00:00:00.77

Es werden alle 10.000 Datensätze im Index gesucht (und gefunden)

FindIn_Index_And_Read 00:00:01.02

Es werden alle 10.000 Datensätze im Index gesucht und dann in der Datenbank auch gelesen.

Create_Fulltext_Index 00:00:04.97

Anlage eines (feldbezogenen) Volltext-Index über alle Felder (Spalten) der Datenbank.

Find_Fulltext_Index 00:00:05.95

100 Volltextsuchen in der ersten Spalten der Tabelle. Jede Suche liefert im Mittel 100 Treffer. Es werden alle Zeilen gefunden.



tdbengine Anwendungen im Web:

Open-Source Web CMS


Open-Source Bug-Tracking


Free wiki hosting

Open-Source Wiki-System

Kostenloses Foren-Hosting

Diät mit tdbengine 8-)

tdbengine chat
irc.tdbengine.org
#tdbengine

   Copyright © 2003-2004 tdb Software Service GmbH
   Alle rechte vorbehalten. / All rights reserved
   Letzte Änderung: 03.03.2004


ranking-charts.de

Programmers Heaven - Where programmers go!