Dynamische Variablen
Übersicht

walskiEhemaliger AdminBetreff: Dynamische Variablen |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Moin,
als Grundstock für meinen geplanten Script-Interpreter hier nuneinmal eine Verwaltung dynamischer Variablen. Sie ist super frisch, kaum debuggt und dürfte daher eher etwas zum lernen oder anschauen sein ![]() Aber ich freue mich natürlich über euer Feedback und über jeden Bugbericht. Das ganze ist eigentlich eine simple Type-Lösung, die ich allerdings um eine Art Cache erweitert habe. Dieser soll dazu dienen, das bei großen Datenbeständen nicht immer alle Variablen durchgegangen werden müssen, sondern das die häufigst aufgerufenen Variablen schneller zu erreichen sind. Sprich: Man hat 100 Variablen, davon nutzt man 95 nur 3 mal, die letzten 5 aber in fast jeder Schleife. Es wäre also ziemlich verschwenderisch jeden Schleifendurchgang alle 100 Einträge durchzugehen, nur um die fünf Variablen herauszufinden, die man eh jede Schleife wieder braucht. Ich habe also eine zweite Typelist mit fester Länge, in der genau diese häufig aufgerufenen Variablen verzeichnet sind und schnell abgerufen werden können, da der Cache eben viel kleiner ist als die gesamte Liste aller Variablen. Die momentan genutze Methode um die "häufig genutzen Variablen" herauszufinden ist ehr einfach und daher sicher noch verbesserungsbedürftig ![]() Ich schaue mir einfach die Zeitdifferenz der letzten fünf Aufrufe der Variable an, und je kleiner die ist, desto häufiger werden sie momentan genutzt ![]() Naja, schaut einfach selbst. Hier erstmal die Funktionssammlung: Code: [AUSKLAPPEN] ;oooooooooooooooooooooooooooooooo; ; Dynamic variables ; ; (c) 2004 by T. Schroeder ; ; netkowalski@web.de ; ;oooooooooooooooooooooooooooooooo; ;oooooooooooooooooooooooooooooooo; ; STATISTIC STUFF ; ONLY FOR DEBUG PURPOSES Global cacheCalled,sumCalled ;oooooooooooooooooooooooooooooooo; ; The type which describes the dynamic variables Type var ; The Name of the variable Field name$ ; The Value of the variable as String, for taking all possible inputs Field value$ ; A field to save the last five times of calling this variable. This is important for caching ; ... purposes Field timestamps[4] ; The idletime between the last five callings Field idleTime End Type ; The type for caching often called variables Type varCache ; Handle of the cached variable Field hndl End Type ; the maximal idle-time which is still in the cache Global dynVarCache_maxIdleTime ; the handle of this "max-idler" Global dynVarCache_maxIdleHndl ; the number of items in the cache Global dynVarCache_count Const dynVarCache_maxItems = 10 ; Function returns the handle of a variable if it's cached or 0 if it's not in the cache [INTEGER] ; Standart Input: Name of the variable [STRING] Function varIsInCache(name$) Local tempVar.var,tempCache.varCache ; cycle through the cache For tempCache.varCache = Each varCache ; converting the handle of the current cache-item to a variable tempVar.var = Object.var( tempCache\hndl ) ; checking the name If tempVar\name$ = name$ Then ; return the handle if the name matched Return tempCache\hndl EndIf Next ;return 0 if there was no match Return 0 End Function ; Function returns the handle of a variable or 0 if it's does not exists [INTEGER] ; Standart Input: Name of the variable [STRING] Function varExists( name$ ) Local tempVar.var,tempHndl ;oooooooooooooooooooooooooooooooo; ; STATISTIC STUFF ; ONLY FOR DEBUG PURPOSES sumCalled = sumCalled + 1 ;oooooooooooooooooooooooooooooooo; ; check if the variable is in the cache tempHndl = varIsInCache( name$ ) If Not tempHndl Then ; cycle through any variable if there was no match in the cache For tempVar.var = Each var If tempVar\name$ = name$ Then ; returns the handle of the current variable if the name matches Return Handle( tempVar.var ) EndIf Next Else ;oooooooooooooooooooooooooooooooo; ; STATISTIC STUFF ; ONLY FOR DEBUG PURPOSES cacheCalled = cacheCalled + 1 ;oooooooooooooooooooooooooooooooo; ; returns the cached handle if the variable was in the cache Return tempHndl EndIf ; returns 0 if the variable does not exist yet Return 0 End Function ; Function for writing something to a variable [VAR] ; Standart Input: Name of the variable [STRING], Value of the variable [STRING] Function writeVar.var( name$,value$ ) Local tempVar.var,tempHndl ; check if a ariable with this name allready exists tempHndl = varExists( name$ ) If Not tempHndl Then ; create a new variable if it does not exist yet tempVar.var = New var ; label the new variable with the given name tempVar\name$ = name$ Else ; if the variable exist convert the handle to an variable-object tempVar.var = Object.var(tempHndl) ; update the timestamps of the variable handleTimestamps( tempVar.var ) EndIf ; set the given value to the variable tempVar\value$ = value$ Return tempVar End Function ; Function for writing an integer to a variable [VAR] ; Standart Input: Name of the variable [STRING], Value of the variable [INTEGER] Function writeVarI.var( name$,value ) Return writeVar( name$,Str( value ) ) End Function ; Function for writing an float to a variable [VAR] ; Standart Input: Name of the variable [STRING], Value of the variable [FLOAT] Function writeVarF.var( name$,value# ) Return writeVar( name$,Str( value# ) ) End Function ; Function to read the value of a variable, it returns an empty string ; ... when the variable does Not exist [STRING] ; Standart Input: Name of the variable [STRING] Function readVar$(name$) Local tempVar.var,tempHndl ; checks the handle of the variable tempHndl = varExists( name$ ) If Not tempHndl Then ; if there was no variable with the given name return an empty string Return "" Else ; convert the returned handle to an variable-object tempVar.var = Object.var( tempHndl ) ; update the timestamps of the variable handleTimestamps( tempVar.var ) ; return the value of the variable Return tempVar\value$ EndIf End Function ; Function to return an integer value of a variable [INTEGER] ; Standart Input: Name of the variable [STRING] Function readVarI(name$) Return Int( readVar$( name$ ) ) End Function ; Function to return an integer value of a variable [FLOAT] ; Standart Input: Name of the variable [STRING] Function readVarF#(name$) Return Float( readVar$( name$ ) ) End Function ; Function to update the timestamps of a variable ; Standart Input: Variable to update [VAR] Function handleTimestamps(tempVar.var) Local i ; shift the older timestamps up For i = 0 To 3 tempVar\timestamps[ i ] = tempVar\timestamps[ i + 1 ] Next ; rewrite the last timestamp with the current time tempVar\timestamps[4] = MilliSecs() ; calculates the idle time ( how long took the last five calls ) tempVar\idleTime = tempVar\timestamps[4] - tempVar\timestamps[0] ; hands over the current variable to the cache management handleCache(tempVar.var) End Function ; Function to check if a variable fits into the cache and then manages this assignment ; Standart Input: Variable to update [VAR] Function handleCache(tempVar.var) Local tempCache.varCache ; updates the cache updateCache ; !!! here you could update the given variable, too. For optimization-processes I forbear from ; ... updating it and assume that this has been done before. If it's not quite sure, that this ; ... is done, you better update the variable if you want to prevent the cache from wrong ; ... results !!! If dynVarCache_count < dynVarCache_maxItems Then ; creates a new cache-item if there are not enough cached items, yet tempCache.varCache = New varCache tempCache\hndl = Handle( tempVar.var ) ; raises the counter of cached items dynVarCache_count = dynVarCache_count + 1 Else If (tempVar\idletime < dynVarCache_maxIdleTime) And ( Not varIsInCache( tempVar\name$ ) ) Then ; deletes the fewest frequented item in the cache if the current variable is more ; ... frequented then this item tempCache.varCache = Object.varCache( dynVarCache_maxIdleHndl ) Delete tempCache.varCache ; create a new cache-item tempCache.varCache = New varCache tempCache\hndl = Handle( tempVar.var ) EndIf EndIf End Function ; Function to update the cache with the current timestamp ; Standart Input: % Function updateCache() Local tempCache.varCache,tempVar.var ; resets the "maximal idle time" of the cache dynVarCache_maxIdleTime = -1 ; cycle through any item of the cache For tempCache.varCache = Each varCache ; convert the current cached handle to an variable-object tempVar.var = Object.var( tempCache\hndl ) ; recalculate the idle-time of this variable tempVar\idleTime = tempVar\timestamps[4] - tempVar\timestamps[0] If tempVar\idletime > dynVarCache_maxIdleTime Or dynVarCache_maxIdleTime = -1 Then ; sets this item as the fewest frequented item in the cache if there is no object ; ... assigned to this position, yet or it actually IS the fewest frequented item dynVarCache_maxIdleTime = tempVar\idleTime dynVarCache_maxIdleHndl = Handle( tempCache.varCache ) EndIf Next End Function Und hier ein kleines Beispiel, das ihr einfach hintendran kopieren könnt. Es simuliert in der Standart-Einstellung 1.000 Variablen, von denen pro Schleifendurchgang 8 zufällig gelesen werden, und 2 immer gleich sind, nämlich Variable 10 und 20. Dadurch erreiche ich eine Cache-Nutzung von 20 Prozent (klingt logisch, oder) ![]() ![]() Momentan erreiche ich in der "as it is" Einstellung und ohne Debug zwischen 160 und 195 FPS, im Schnitt sind es etwa 170. Code: [AUSKLAPPEN] howMuchVars = 1000 For i = 1 To howMuchVars If i Mod 100 = 0 Then Cls:Locate 1,1:Print "Loading: " + Str(Float(i) / (howMuchVars / 100.0)) + "%" writeVar(Str(i),"Var: " + Str(i)) Next Graphics 640,480,16,2 SetBuffer BackBuffer() SeedRnd MilliSecs() While Not KeyHit(1) Cls Text 5,0,"Name:|Time 0|Times 1|Time 2|Time 3|Times 4|IdleTime" Text 5,220, "Current called Variables:" Text 550,0,"FPS: " + Str(fps) Text 500,20,"maxIdleTime: " + Str(dynVarCache_maxIdleTime) Text 5,460,Str(sumCalled) + " Variables called. " + Str(cacheCalled) + " from the cache, which makes " + Str(Float(cacheCalled) / (sumCalled / 100.0)) + "%" i = 0 For tempCache.varCache = Each varCache tempVar.var = Object.var(tempCache\hndl) Text 5,20 + i,tempVar\name$ + " - " + Str(tempVar\timestamps[0]) + " - " + Str(tempVar\timestamps[1]) + " - " + Str(tempVar\timestamps[2]) + " - " + Str(tempVar\timestamps[3]) + " - " + Str(tempVar\timestamps[4]) + " : " + Str(tempVar\idleTime) i = i + 20 Next For i = 0 To 7 iRand = Rand(0,howMuchVars) bcc = cacheCalled a$ = readVar(Str(iRand)) If cacheCalled > bcc Then Color 0,255,0 EndIf Text 5,240 + i * 20,Str(i) + ": " + a$ Color 255,255,255 Next ;simulate two very frequented variables bcc = cacheCalled a$ = readVar(Str(Rand(1,5))) If cacheCalled > bcc Then Color 0,255,0 EndIf Text 5,240 + 8 * 20,Str(8) + ": " + a$ Color 255,255,255 bcc = cacheCalled a$ = readVar(Str(Rand(6,10))) If cacheCalled > bcc Then Color 0,255,0 EndIf Text 5,240 + 9 * 20,Str(9) + ": " + a$ Color 255,255,255 tTime = MilliSecs() If lastFpsTime + 1000 < tTime Then lastFpsTime = tTime fps = fpsCount fpsCount = 0 EndIf fpsCount = fpsCount + 1 Flip 0 Wend Bitte beschwert euch nicht über den lausigen Stil des Beispiels, aber das war auch eigentlich nur für mich selbst, zum testen gedacht. Aber da ich dachte, dass manche von euch evtl Lust haben mitzutesten: Bitte Schön! *g Ich würde mich wirklich sehr über eure Ergebnisse (vor allem mit verschiedenen Einstellungen etc) freuen und möchte euch ermuntern, eure Meinung zu der ganzen Cache Idee zu verkünden. Gute Nacht walski [EDIT] In der Funktionssammlung haben sich zwei kleine aber bedeutende Fehler eingeschlichen, die ich nun berichtigt habe. Außerdem habe ich das Beispiel etwas erweitert, aber kaum merklich. [/EDIT] |
||
buh! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group