Hallo bfuerchau,
ist das nicht der aktuelle Code nicht hier zu finden:
https://github.com/FirebirdSQL/NETProvi ... 568d4340d9
Für mich sieht das doch aktuell aus oder nicht?
Gruß
Martin
Firebird 5 geht in den Beta-Test
Moderator: martin.koeditz
- martin.koeditz
- Beiträge: 447
- Registriert: Sa 31. Mär 2018, 14:35
Martin Köditz
it & synergy GmbH
it & synergy GmbH
Das ist nur zum Teil korrekt, da die Dateien nicht gemerged sind.
Die gemergten Sourcen stehen dann hier:
https://github.com/BFuerchau/NETProvide ... au-patch-1
Ich sollte ja separate pull requests machen, was aber mangels Wissen meinerseits nicht so einfach ist. Ich habe zwar 2 Requests, aber beide enthalten nun alle 3 Dateien.
Im Patch-1 habe ich aber noch eine Korrektor bzgl. impliziter Transaktion bei GetSchema einbauen müssen.
Allerdings sind bisher noch keine Reaktionen eingetroffen.
Die gemergten Sourcen stehen dann hier:
https://github.com/BFuerchau/NETProvide ... au-patch-1
Ich sollte ja separate pull requests machen, was aber mangels Wissen meinerseits nicht so einfach ist. Ich habe zwar 2 Requests, aber beide enthalten nun alle 3 Dateien.
Im Patch-1 habe ich aber noch eine Korrektor bzgl. impliziter Transaktion bei GetSchema einbauen müssen.
Allerdings sind bisher noch keine Reaktionen eingetroffen.
Zurück zum Thema (Firebird 5 Beta):
In Firebird 5 gab es jetzt eine Änderung bzgl des Defaults für Parallelisierung. Bisher musste für Backup oder Restore über Service Mgr (was viele connectivity libs nutzen) explizit ein neuer Parameter (zb isc_spb_res_parallel_workers) mit der gewünschten Anzahl der parallelen Prozesse in den SPB (service parameter block) eingetragen werden, damit auch Backup/Restore über Service Mgr die Parallelisierung genutzt hat. Das erschien nicht nur mir unlogisch, da der Service Mgr die Konfiguration aus firebird.conf über die Firebird-engine beziehen kann. Wenn man also schon in firebird.conf mittels ParallelWorkers konfiguriert, wie viele parallele Prozesse die Kiste für Firebirds parallele Aktionen zur Verfügung stellen kann, sollte auch der Service Mgr seinen Default für die Parallelverarbeitung von da beziehen. Auf diese Weise muss nicht der Großteil der Anwendungsentwickler ihre connectivity-libs patchen, um das neue Feature auch über services nutzen zu können, denn die libs sind bis auf wenige Ausnahmen (Java, python) Jahre hinter der Firebird-Entwicklung zurück.
Und das ist jetzt so umgesetzt und in Firebird 5 ab Build 1145 drin. Es reicht also, in firebird.conf ParallelWorkers auf einen Wert > 1 zu setzen, und ohne eine einzige Zeile Code ändern zu müssen, machen jetzt auch connectivity libs, die nicht auf dem neuesten Stand von Firebird 5 sind, ihr backup/restore zigmal so schnell wie bisher. Sehr schön.
gbak ist als Kommandozeilen-Utility davon nicht tangiert, denn a) gibt es dort Aufrufparameter für Parallelisierung , die man einfach setzen kann und b) kommt gbak als separate Utility nicht an Einstellungen aus firebird.conf ran.
![Zwinkern ;)](./images/smilies/icon_e_wink.gif)
In Firebird 5 gab es jetzt eine Änderung bzgl des Defaults für Parallelisierung. Bisher musste für Backup oder Restore über Service Mgr (was viele connectivity libs nutzen) explizit ein neuer Parameter (zb isc_spb_res_parallel_workers) mit der gewünschten Anzahl der parallelen Prozesse in den SPB (service parameter block) eingetragen werden, damit auch Backup/Restore über Service Mgr die Parallelisierung genutzt hat. Das erschien nicht nur mir unlogisch, da der Service Mgr die Konfiguration aus firebird.conf über die Firebird-engine beziehen kann. Wenn man also schon in firebird.conf mittels ParallelWorkers konfiguriert, wie viele parallele Prozesse die Kiste für Firebirds parallele Aktionen zur Verfügung stellen kann, sollte auch der Service Mgr seinen Default für die Parallelverarbeitung von da beziehen. Auf diese Weise muss nicht der Großteil der Anwendungsentwickler ihre connectivity-libs patchen, um das neue Feature auch über services nutzen zu können, denn die libs sind bis auf wenige Ausnahmen (Java, python) Jahre hinter der Firebird-Entwicklung zurück.
Und das ist jetzt so umgesetzt und in Firebird 5 ab Build 1145 drin. Es reicht also, in firebird.conf ParallelWorkers auf einen Wert > 1 zu setzen, und ohne eine einzige Zeile Code ändern zu müssen, machen jetzt auch connectivity libs, die nicht auf dem neuesten Stand von Firebird 5 sind, ihr backup/restore zigmal so schnell wie bisher. Sehr schön.
gbak ist als Kommandozeilen-Utility davon nicht tangiert, denn a) gibt es dort Aufrufparameter für Parallelisierung , die man einfach setzen kann und b) kommt gbak als separate Utility nicht an Einstellungen aus firebird.conf ran.
jetzt schreib ich doch mal dazu, obwohl ein neuer Thread wirklich sinnvoller wäre: 2 Mio Sätze kommen vor, klar, auch 10. Aber nicht im Dashboard. Du musst zusehen, dass Du die Daten auf dem Server aggregierst und nicht erst alle zum Client schaffst. Der Transport von Massendaten ist teuer, nicht die Aggregierung. Ein Dashboard zeigt per Definition eine Auswahl von Kennzahlen und verdichtete Auswertungen, aber nie 2 Mio Sätze.
Außerdem spielt die Satzbreite eine große Rolle. Ich hab bei Tests zur Insertperformance von Firebird festgestellt, dass die Satzbreite der entscheidende Faktor ist. Mit schmalen Tabellen kriegst Du eine satte Insertrate, aber wenn die Tabelle Richtung 64K Satzbreite geht, kannst Du froh sein, wenn es 30K Sätze/sek gibt. Gut, das war insert und nicht select wie bei Dir.
Weiter spielt Single-Thread-Performance der CPU und SSD eine Rolle, wieviel, kannst Du sehen, wenn Du ein zweites Mal abfragst, um Cache-Effekte (kalt/warm, Windows-File-Cache, Firebird-Page-Cache) einschätzen zu können (SSDs sind sehr unterschiedlich mittlerweile, die wahlfreie Leserate ist wichtig, nicht die sequentielle) und natürlich Virtualisierung. Viele Virtualisierungen sind standardmäßig für Office-Anwendungen konfiguriert, das ist für BI-Anwendungen völliger Quatsch. Bei BI-Anwendungen darf die VM nicht erst nachgucken, ob sie gemächlich CPU oder IO nachlegt, sondern da muss jederzeit die volle Power bereitstehen. Auch das nur zur der Vollständigkeit halber. nicht ganz entlang Deiner Beschreibung, da Du auf Deinem nicht virtualisierten Laptop getestet hast - was oft bessere Performance bringt als eine VM auf einem fetten Server, wenn die suboptimal konfiguriert ist.
Übrigens "Read Uncommitted" gibt es technisch nicht bei Firebird, das ist ein Synonym für "Read Committed", aus Kompatibilitätsgründen, siehe https://firebirdsql.org/file/documentat ... rence.html, Abschnitt 12.1.1. SET TRANSACTION:
The READ UNCOMMITTED isolation level is a synonym for READ COMMITTED, and provided only for syntax compatibility. It provides the exact same semantics as READ COMMITTED, and does not allow you to view uncommitted changes of other transactions.
Grüße, Volker
So, leider sind meine Ergänzungen zum Firebird-Provider nicht übernommen worden.
Somit muss ich diese bei jeder neuen Version immer wieder selber implementieren und testen.
Es wäre ja auch zu schön gewesen.
Wenn z.B. eine Abfrage "Select * from MyTable" gemacht wird, wird intern je Feld eine separate Abfrage an die DB durchgeführt um Metadaten des Feldes zu laden.
Bei 50 Spalten macht das eben 50 zusätzliche Queries.
Jeder Query dauert z.B. ca. 10ms, was in Summe zwar auch nur 500ms sind, wenn das aber eben viele machen, summiert sich das. Wenn man nur 1 Query für alle Felder macht, dauert das auch nur 10ms! Die Hauptzeit ist also nicht die DB-Abfrage sondern das API und die Transportwege.
In .Net gibts auch Performanceprobleme mit dem Garbage-Collector.
Für jede Zeile und je Spalte wird intern ein Verwaltungsobjekt erstellt, das den Objekt-Wert enthält.
Der FbDataReader liest dann den Objekt-Wert aus und das Verwaltungsobjekt wird dereferenziert.
Beim Laden von 1 Mio. Zeilen á 30 Spalten werden also 30 Mio. Objekte erstellt und wieder dereferenziert.
Im Profiler kann man dann sehr schön sehen, dass der Garbagecollectior all paar Sekunden aufräumen muss, was ca. 20% der Gesamtlaufzeit der Abfrage ausmacht.
Bei kürzeren Abfragen fällt der Garbage da eher seltener auf.
Beim Laden einer DataTable, z.B. durch einen FbDataAdapter wird die Funktion des FbDataReader's GetValues(object[] values) bemüht. Diese führt intern dann je Spalte die GetValue(int ordinal) auf. Diese prüft dann immer wieder den Status des Readers sowie den ArrayIndex des Ordinals vor dem Zugriff auf das Value-Objekt.
Dies kostet ca. weitere 10%.
Insgesamt könnte der Reader also 30% schneller sein, was der Anwendung zu gute kommt und den DB-Server entlastet, so dass dieser durchaus mehr Abfragen in derselben Zeit durchführen kann.
Aber was solls, somit bin ich wohl der Einzige, der von diesen Vorteilen profitieren kann.
Somit muss ich diese bei jeder neuen Version immer wieder selber implementieren und testen.
Es wäre ja auch zu schön gewesen.
Wenn z.B. eine Abfrage "Select * from MyTable" gemacht wird, wird intern je Feld eine separate Abfrage an die DB durchgeführt um Metadaten des Feldes zu laden.
Bei 50 Spalten macht das eben 50 zusätzliche Queries.
Jeder Query dauert z.B. ca. 10ms, was in Summe zwar auch nur 500ms sind, wenn das aber eben viele machen, summiert sich das. Wenn man nur 1 Query für alle Felder macht, dauert das auch nur 10ms! Die Hauptzeit ist also nicht die DB-Abfrage sondern das API und die Transportwege.
In .Net gibts auch Performanceprobleme mit dem Garbage-Collector.
Für jede Zeile und je Spalte wird intern ein Verwaltungsobjekt erstellt, das den Objekt-Wert enthält.
Der FbDataReader liest dann den Objekt-Wert aus und das Verwaltungsobjekt wird dereferenziert.
Beim Laden von 1 Mio. Zeilen á 30 Spalten werden also 30 Mio. Objekte erstellt und wieder dereferenziert.
Im Profiler kann man dann sehr schön sehen, dass der Garbagecollectior all paar Sekunden aufräumen muss, was ca. 20% der Gesamtlaufzeit der Abfrage ausmacht.
Bei kürzeren Abfragen fällt der Garbage da eher seltener auf.
Beim Laden einer DataTable, z.B. durch einen FbDataAdapter wird die Funktion des FbDataReader's GetValues(object[] values) bemüht. Diese führt intern dann je Spalte die GetValue(int ordinal) auf. Diese prüft dann immer wieder den Status des Readers sowie den ArrayIndex des Ordinals vor dem Zugriff auf das Value-Objekt.
Dies kostet ca. weitere 10%.
Insgesamt könnte der Reader also 30% schneller sein, was der Anwendung zu gute kommt und den DB-Server entlastet, so dass dieser durchaus mehr Abfragen in derselben Zeit durchführen kann.
Aber was solls, somit bin ich wohl der Einzige, der von diesen Vorteilen profitieren kann.
Alles im offiziellen Weg:
https://github.com/FirebirdSQL/NETProvider/pull/1121
https://github.com/FirebirdSQL/NETProvider/pull/1122
Fork:
https://github.com/BFuerchau/NETProvider
Ich habe auch alle vorhandenen Tests, soweit es mir möglich ist, duchgeführt.
Manche der Tests konnte man nicht automatisch mitlaufen lassen, sondern musste sie explizt aufrufen.
Manche Antworten des Entwicklers sind da unverständlich, da die Vorteile auch bei kleineren Abfragen durchaus nicht unerheblich sind, da bei Multiuserbetrieb via Server die FB sogar entlastet wird und mehr Durchsatz schafft. Im Embedded-Mode trifft es nur den einzelnen User, und da merkt man natürlich nicht, ob eine Abfrage 0,5 oder nur 0,3 Sekunden dauert. Bei 30 zu 20 Sekunden merkt man das aber schon. Bei komplexen Abfragen, die die DB tatsächlich fordert, bringt es dann wieder weniger.
Konkret wird es dann bei Web-Anwendungen, bei denen viele Abfragen parallel gestellt werden.
Hier musste ich nun sogar eine "begrenztes" Pooling bauen, um die Abfragen zu queuen um den DB-Server nicht mit Threads zu überfrachten. Z.B. nur 1 Abfrage je CPU.
Gerade morgens beim allgemeinen Start der User hatte ich z.T. über 100 Queries parallel und die DB war im Stillstand. Durch Reduktion der prallelen Queries aber Beschleunigung der Downloadzeiten von der DB normalisierte sich das Verhalten wieder.
Man kann sogar noch eine weitere Beschleunigung einbauen, was allerdings nicht funktioniert, wenn BLOB-Objekte im Spiel sind. Dies müsste man dann in 2 Varianten behandeln, was aber durchaus ginge. Ein Performanceschub von weiteren 10-15% waren da drin, da ich komplett ohne die Queue in den GdsStatements auskommen könnte.
https://github.com/FirebirdSQL/NETProvider/pull/1121
https://github.com/FirebirdSQL/NETProvider/pull/1122
Fork:
https://github.com/BFuerchau/NETProvider
Ich habe auch alle vorhandenen Tests, soweit es mir möglich ist, duchgeführt.
Manche der Tests konnte man nicht automatisch mitlaufen lassen, sondern musste sie explizt aufrufen.
Manche Antworten des Entwicklers sind da unverständlich, da die Vorteile auch bei kleineren Abfragen durchaus nicht unerheblich sind, da bei Multiuserbetrieb via Server die FB sogar entlastet wird und mehr Durchsatz schafft. Im Embedded-Mode trifft es nur den einzelnen User, und da merkt man natürlich nicht, ob eine Abfrage 0,5 oder nur 0,3 Sekunden dauert. Bei 30 zu 20 Sekunden merkt man das aber schon. Bei komplexen Abfragen, die die DB tatsächlich fordert, bringt es dann wieder weniger.
Konkret wird es dann bei Web-Anwendungen, bei denen viele Abfragen parallel gestellt werden.
Hier musste ich nun sogar eine "begrenztes" Pooling bauen, um die Abfragen zu queuen um den DB-Server nicht mit Threads zu überfrachten. Z.B. nur 1 Abfrage je CPU.
Gerade morgens beim allgemeinen Start der User hatte ich z.T. über 100 Queries parallel und die DB war im Stillstand. Durch Reduktion der prallelen Queries aber Beschleunigung der Downloadzeiten von der DB normalisierte sich das Verhalten wieder.
Man kann sogar noch eine weitere Beschleunigung einbauen, was allerdings nicht funktioniert, wenn BLOB-Objekte im Spiel sind. Dies müsste man dann in 2 Varianten behandeln, was aber durchaus ginge. Ein Performanceschub von weiteren 10-15% waren da drin, da ich komplett ohne die Queue in den GdsStatements auskommen könnte.
VS Code könnte klappen, besser wäre VS 2022 Community.
.Net 4.8 sowie .Net Core 6 oder 7.
Möchtest du nur die Laufzeit vergleichen?
Dann kann ich dir das nuget zur Verfügung stellen. Zum Upload ist es allerdings zu groß.
.Net 4.8 sowie .Net Core 6 oder 7.
Möchtest du nur die Laufzeit vergleichen?
Dann kann ich dir das nuget zur Verfügung stellen. Zum Upload ist es allerdings zu groß.