Delphi-PRAXiS
Seite 12 von 12   « Erste     2101112   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   ScriptEngine II (v. 0.6.1) (https://www.delphipraxis.net/140590-scriptengine-ii-v-0-6-1-a.html)

WorstNightmare 2. Jan 2011 14:58

AW: ScriptEngine II (v. 0.6)
 
Hi,

ich denke gerade darüber von RemObjects PascalScript auf deine ScriptEngine umzusteigen, aus dem einfachen Grund weil hier overloading unterstützt wird. Eines stört mich jedoch: Die Scripts müssen immer einen program-Header haben, in PascalScript konnte man den abschalten (über CompilerOptions). Kannst du das auch abschaltbar machen? Der verschwendet bei mir nur Platz, da ich ihn eh immer NPCScript oder so nennen würde und die Scripts über Dateinamen identifiziert werden.

Edit: Und gibt es irgendwo Inc() und Dec()? Wenn nein, warum nicht?

Edit 2: So, läuft ganz gut jetzt. Allerdings habe ich noch einen Feature-Wunsch:
Meine Scripts terminieren die Runtime aus sich heraus und wenn ich direkt nach Abort() Finalize() und Free() aufrufe, knallt es. Daher brauche ich ein Notify-Event, irgendwie OnAborted oder so in der Runtime. Im finally ganz unten in TSE2ExecutionContext.Call dann so aufrufen:
Delphi-Quellcode:
    if FDoAbort and Assigned(FOnAborted) then
      FOnAborted(TObject(FExecutionData.RunTime));

littleDave 4. Jan 2011 20:23

AW: ScriptEngine II (v. 0.6)
 
Hallo WorstNightmare,

sorry für die späte Antwort, bin bisher nicht dazu gekommen

Zitat:

ich denke gerade darüber von RemObjects PascalScript auf deine ScriptEngine umzusteigen, aus dem einfachen Grund weil hier overloading unterstützt wird. Eines stört mich jedoch: Die Scripts müssen immer einen program-Header haben, in PascalScript konnte man den abschalten (über CompilerOptions). Kannst du das auch abschaltbar machen?
Ja, ich werde schauen, was sich da machen lässt. Wird jedoch noch etwas dauern, da ich mich endlich dazu überwunden habe und im Moment arrays einbaue. Ich bin dabei gerade mitten in der Implementierungs- und Testphase. Dadurch wäre es im Moment nicht so gut, den halbfertigen Code herauszugeben. Bis dahin kannst du ja vor dem Übergeben an den Compiler folgendes schreiben:
Delphi-Quellcode:
function CompileScript(const Source: string): TSE2PE;
begin
  result := Compiler.Compile('program program1; ' + Source + ' begin end.';
end;
Zitat:

Edit: Und gibt es irgendwo Inc() und Dec()? Wenn nein, warum nicht?
Diese Routinen habe ich zum einen aus Zeitgründen, zum anderen aus Featuregründen noch nicht drinnen (ich will eigentlich keine "Compiler-Magic" einbauen).
  • Zeitgrund: für jeden Typ müssen die Routinen alle manuell deklarieren muss (also für byte, integer, etc. - jeweils mit und ohne Parameter).
  • Feature-Grund: für ein einfaches "+1" eine einzelne Funktion aufrufen ist doch etwas overhead, daher wollte ich warten, bis ich "inline" - Methoden eingebaut habe.
Bei "pred()" und "succ()" hört der Spaß dann aber auf - die kommen mir nicht in die System-Unit :twisted: (ich finde die total unübersichtlich)

Zitat:

Edit 2: So, läuft ganz gut jetzt. Allerdings habe ich noch einen Feature-Wunsch:
Meine Scripts terminieren die Runtime aus sich heraus und wenn ich direkt nach Abort() Finalize() und Free() aufrufe, knallt es. Daher brauche ich ein Notify-Event, irgendwie OnAborted oder so in der Runtime. Im finally ganz unten in TSE2ExecutionContext.Call dann so aufrufen:
Delphi-Quellcode:
    if FDoAbort and Assigned(FOnAborted) then
      FOnAborted(TObject(FExecutionData.RunTime));

Das versteh ich nicht, wieso das nötig sein sollte. Gehe ich richtig in der Annahme, dass du im Script einen Methode aufrufst, die die RunTime beenden und schließen soll? Das kann nicht funktionieren! denn so ziehst du dem Script die RunTime unter den Füßen weg und knallt somit auf den Boden. Die RunTime darf nicht von einer Funktion heraus gelöscht werden, wenn diese aus der RunTime heraus aufgerufen wird.

EugenB 5. Jan 2011 18:47

AW: ScriptEngine II (v. 0.6)
 
Hi :)

Zitat:

Zitat von littleDave (Beitrag 1072265)
Zitat:

Edit: Und gibt es irgendwo Inc() und Dec()? Wenn nein, warum nicht?
Diese Routinen habe ich zum einen aus Zeitgründen, zum anderen aus Featuregründen noch nicht drinnen (ich will eigentlich keine "Compiler-Magic" einbauen).

Wäre sowas nicht "einfach" durch ne Helper-Klasse besser realisiert?

IntVar.Inc;
IntVar.Dec;

Oder geht sowas nicht bei einfachen Variablen?

Btw, schön zu hören das es bald Arrays gibt, obwohl man jetzt sowieso alles mit Listen machen würde (ich zumindest :)

Btw2, ist es möglich / auf der Todo Liste, dass man Generics nutzen kann?

Gruß
Eugen

WorstNightmare 5. Jan 2011 22:57

AW: ScriptEngine II (v. 0.6)
 
Mein RTTI-ClassImporter fügt jetzt einfach noch nach der Klasse, mit der das Script aufs Hauptprogramm zugreift, Inc und Dec für Integer ein. Ich hatte einfach keine Lust das in allen 250 Scripts mit + bzw - 1 zu ersetzen.

Zum Abbrechen der Runtime:
Das habe ich dann auch schnell festgestellt^^
Deswegen möchte ich ja, dass wenn ich Abort aufrufe, ich benachrichtigt werde wenn es fertig mit Abbrechen ist und dann Free aufrufen kann. Eine andere Möglichkeit habe ich nicht, denn das Hauptprogramm weiß nicht automatisch, wann das Script fertig ist (die Teile haben eine Methode, die bei jedem Script unterschiedlich oft aufgerufen wird).

WorstNightmare 18. Mär 2011 14:26

AW: ScriptEngine II (v. 0.6)
 
Alle meine Scripts laufen jetzt schon seit längerer Zeit mit dieser Engine und ich muss sagen, ich bin sehr zufrieden.

Es gibt allerdings ein mittelschweres Problem: Der Speicherverbrauch.

Für ein simples Script wie dieses [Link] fallen knapp 5 (!) MB Speicher an, sobald Compile() ausgeführt wurde. Das Problem an diesen Event-Scripts ist, dass sie für jeden Channel-Server (wovon es durchschnittlich 6 gibt) extra instanziert werden müssen und die ganze Zeit aktiv sein müssen, da sie oft auch zeitgesteuerte Aufträge haben und Variablen über einen längeren Zeitraum speichern. Momentan gibt es zwar nur dieses eine, wenn allerdings später 15 vorhanden sind ist dieser extreme Verbrauch echt nicht mehr tragbar.

Ich bin nicht ganz sicher warum für ein 600 Byte langes Script plötzlich 4,5 MB verbraucht werden, könnte es mit der verwendeten Unit zusammenhängen? Diese setzt sich aus den Klassen TEventInstance und TEventManager aus dieser Datei und TScriptMapleCharacter zusammen. In der letzteren Datei ist auch der RTTI Class-Importer.

littleDave 18. Mär 2011 15:16

AW: ScriptEngine II (v. 0.6)
 
Es gibt mehrere Caching-Systeme in der Script-Engine, die ich kurz erläutern will.
  • Compiler-Cache
    Der Compiler-Cache (TSE2UnitCacheMngr) hilft für die schnellere Re-Compilierung von Scripts. Er ist vergleichbar mit .DCU-Dateien in Delphi. Dort drinnen stehen relativ viele Informationen, d.h. es kann sehr schnell zur 5 MB Speicherverbrauch kommen. Auf den Manager kann ohne Probleme verzichtet werden, da er nur optional ist. Nachteil ist dann aber, dass bei jedem Compile() alle Script-Units erneut kompiliert werden müssen. Eine Zwischenlösung gibt es aber: die Klasse "TSE2UnitCacheMngr" bietet ein (noch undokumentiertes) Event an ("OnGetCacheStream"), in dem man einen Stream angeben kann, in der der Compiler-Output hinein- bzw. heraus-serialisiert wird. Dort könnte man z.B. einen TFileStream übergeben, womit der RAM entlastet wird. Setzt man in dem Event den Parameter "Cache" auf "nil", wird automatisch ein TMemoryStream angelegt und verwendet.

    Die Script-Engine ist beim kompilieren zwar nicht die langsamste, aber wirklich schnell ist sie nicht. Das liegt daran, dass ich eher darauf Wert gelegt habe, die fertig kompilierten Scripts zu speichern und diese dann schnell zu laden. Die fertig kompilierten Scripts sind relativ klein und können so zum einen schnell geladen werden und zum anderen verbrauchen diese nicht so viel RAM.
  • RunTime-Cache (pro RunTime-Instanz)
    Die RunTime hat auch einen Memory-Cache, der die Ausführungsgeschwindigkeit erhöht. Dieser Cache vermindert das ständige Abfragen und Freigeben von RAM vom/zum Betriebssystem, in dem es einen fixen Memory-Block anfragt und mit diesem arbeitet. Falls für ein Script mehr Arbeitsspeicher benötigt wird als in diesen Block passen, greift SEII wieder auf "GetMem()" und "FreeMem()" zurück.

    Die Größe dieses Caches ist in 3 Stufen einstellbar. Komplett aus - klein - und groß. Diese Konfiguration ist über die Datei "ScriptEngine.inc" zu lösen und somit während der Laufzeit nicht änderbar.
  • RunTime-Helper-Cache (pro Thread innerhalb eines RunTime-Objekts)
    Zusätzlich zum Memory-Cache gibt es noch einen Cache für die Verwaltungsobjekte innerhalb der Script-RunTime. Dieser Cache ist Thread-Bezogen, da er für den Execution-Stack der RunTime verwantwortlich ist.

    Dieser Cache ist nicht deaktivierbar, ist jedoch sehr klein (ca. 2,5 kb)
Ich hoffe, ich konnte dir mit der Beschreibung etwas weiterhelfen.

Wegen dem Implementierungsfortschritt: die Arrays sind soweit drinnen und funktionieren auch fast ohne Probleme (gibt noch ein paar Baustellen). Jedoch habe ich im Moment wenig Zeit, wodurch sich der Release leider etwas verzögert. Vielleicht bringe ich zur Überbrückung auch noch ein Zwischen-Release heraus, in der die Arrays noch deaktiviert sind, da ich doch noch ein paar kleine Fehler entdeckt habe.

Gruß
David

Denstern 23. Mär 2011 08:01

AW: ScriptEngine II (v. 0.6)
 
Hallo an Alle. Zuerst muss ich sagen: SUPER Sache!!! Und grooooßßßßesss Lob an David!!!! 8-)
So ein SciptEngine ist gerade das was ich schon lange gesucht habe. Ich habe aber eine Frage diesbezüglich:
Im wesentlichen brauche ich nur ein Zugriff vom Hauptprogramm auf die Script-Funktionen.

Frage 1): Gibt es ein allgemeiner Aufruf einer Funktion? (ohne Benutzung von TSE2RunAccess.FindMethod ?) Bei mir ist es der Fall dass die Funktionen im Script vom Anwender Definiert
werden und ich diese dann zur Laufzeit aufrufen will.

Frage 2): Kann man auf Funktionen mit den Arrays für solche zwecke verwenden? Ich habe eigentlich in den ParamTypes kein Array gefunden.

Ich hoffe ihr könnt mir Helfen.

Danke im Voraus,
Denis.

littleDave 10. Apr 2011 14:12

AW: ScriptEngine II (v. 0.6.1)
 
Neue Version :arrow: Version 0.6.1

Vor längerer Zeit habe ich ja eine neue Version angekündigt. Nun ist es soweit - wobei ich gleich sagen muss: arrays sind immer noch nicht fertig eingebaut. Somit ist das hier eher ein Bug-Fix-Release sowie eine experimentelle Version für arrays. Es ist noch nicht alles drinnen aber ich habe Arrays jetzt erstmal nicht deaktiviert.

Falls also wer die Arrays mal ausprobieren will, es geht noch nicht alles. Zudem gibt es folgende wichtige Einschränkung: man kann arrays nicht "inline" deklarieren, also folgendes geht NOCH NICHT:
Delphi-Quellcode:
var t: array of integer;
. Stattdessen muss man immer vorher den Array-Typ deklarieren:
Delphi-Quellcode:
type TIntArray = array of integer;
.
  • Neuerungen
    • Basis-Array-Implementation eingebaut
    • Die Funktionen "System.Inc()" sowie "System.Dec()" sind jetzt vorhanden
  • Veränderungen
    • Performance bei Conditional-Jumps verbessert
    • Byte-Code-Optimizer erweitert und verbessert
  • Bug-Fixes
    • Fehler beim Aufrufen von überladenen Methoden mit var-Parameter behoben
    • Das Forwarden von Klassen war im Compiler nicht komplett - somit war die erstellte Klasse im Code nicht verwendbar. Dies trat in normalen Units nicht auf, da man da die Deklaration zuerst abschließen musste - in der "program" - Datei jedoch war das nicht zwingend notwendig.
    • Fehler beim Finden der korrekten, überlandenen Methode behoben, falls zwei verschiedene Klassentypen als Parameter-Varianz ausschlaggebend waren
    • Fehler bei break/continue innerhalb von try-except-Blöcken, die sich innerhalb eines try-finally-Blocks befanden, behoben
    • Fehler bei exit innerhalb eines try-finally-Blocks unter bestimmten Umständen
    • Fehler beim Aufrufen von Script-Methoden aus dem Delphi-Programm heraus mit double-var-Parametern (Danke an Denstern)

Download-Link ist im ersten Post.

Grüße

Piethan 4. Aug 2011 09:23

AW: ScriptEngine II (v. 0.6.1)
 
Morgen David,

ich möchte mich in deine ScriptEngine einarbeiten, dabei plane ich Funktionen zu schreiben, welchen ich die Parameter als Array (
Delphi-Quellcode:
type TMyRecordList = array of TMyRecord;
) übergeben möchte.

Folgenden Aufruf hatte ich daher von Seite der Delphi-Anwendung gedacht:
Delphi-Quellcode:
Method := RunTime.CodeAccess.FindMethod('get_Test', 'Records', [pmIn, pmResult], [btArray,btDouble]);
     if Method <> nil then
         ShowMessage(FloatToStr(RunTime.Call(Method, [MyRecordList])));

In der ScriptEngine sieht die Definition wie folgt aus:
Delphi-Quellcode:
type TMyRecordList = array of TMyRecordList;

implementation

function get_Test(MyRecordList: TMyRecordList): double; export;
begin
result:= MyRecordList[0].dbl_Betrag * 3.5;
end;
Die unit Records habe ich sowohl für Delphi und der ScriptEngine geschrieben. Da du ja bei den Arrays noch in der Entwicklung bist, interessiert mich, ob ich etwas falsch verstanden habe oder ob mein Weg so noch nicht möglich ist?

LG
Dirk


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:34 Uhr.
Seite 12 von 12   « Erste     2101112   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz