From d7fbb178a7878ba144ea1606cfbee221ae6d742b Mon Sep 17 00:00:00 2001 From: Vitali Graf Date: Sun, 28 Dec 2025 17:30:20 +0100 Subject: [PATCH] Feature: Konfigurierbare SaxonWorkerPool-Aktivierung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Performance-Dialog erweitert um Checkbox zur Aktivierung/Deaktivierung des SaxonWorkerPool. Benutzer können jetzt zwischen Worker-Pool (schnell, benötigt JDK) und Fallback-Modus (robust, nur JRE) wählen. Änderungen: - Neue Einstellung 'use_saxon_worker_pool' in AppSettings (Standard: aktiviert) - Erweiterter Performance-Dialog mit zwei Sektionen (ThreadPoolExecutor + SaxonWorkerPool) - Pool-Initialisierung prüft nun Einstellung vor Worker-Start - Aktualisiertes Menü-Tooltip zeigt beide Einstellungen 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/conf.py | 1 + src/ui/MainWindow.py | 132 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 112 insertions(+), 21 deletions(-) diff --git a/src/conf.py b/src/conf.py index 94522e0..01e1f39 100644 --- a/src/conf.py +++ b/src/conf.py @@ -143,6 +143,7 @@ class AppSettings(BaseSettings): postgresql_dbs: list[PostgreSqlDb] = [] theme: str | None = None max_workers: int = 8 # Anzahl paralleler Worker für Transformationen (Standard: 8) + use_saxon_worker_pool: bool = True # SaxonWorkerPool aktivieren (schneller, benötigt JDK) # UI-Zustand window_geometry: tuple[int, int, int, int] | None = None # (x, y, width, height) diff --git a/src/ui/MainWindow.py b/src/ui/MainWindow.py index 19d4747..1197c6a 100644 --- a/src/ui/MainWindow.py +++ b/src/ui/MainWindow.py @@ -655,7 +655,10 @@ class MainWindow(QMainWindow): # Erstelle Aktion für Performance-Einstellungen performance_action = QAction("Performance-Einstellungen...", self) - performance_action.setToolTip(f"Parallele Worker: {app_settings.max_workers}") + pool_status = "aktiviert" if app_settings.use_saxon_worker_pool else "deaktiviert" + performance_action.setToolTip( + f"Worker: {app_settings.max_workers} | SaxonWorkerPool: {pool_status}" + ) performance_action.triggered.connect(self._open_performance_settings) # Füge die Aktion zum Projekt-Menü hinzu @@ -665,29 +668,110 @@ class MainWindow(QMainWindow): def _open_performance_settings(self): """Öffnet einen Dialog für Performance-Einstellungen.""" - from PySide6.QtWidgets import QInputDialog + from PySide6.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QSpinBox, QCheckBox, QPushButton, QGroupBox - current_workers = app_settings.max_workers - new_workers, ok = QInputDialog.getInt( - self, - "Performance-Einstellungen", - "Anzahl paralleler Worker für Transformationen:", - current_workers, # value - 1, # minValue - 32, # maxValue - 1, # step + # Erstelle benutzerdefinierten Dialog + dialog = QDialog(self) + dialog.setWindowTitle("Performance-Einstellungen") + dialog.setMinimumWidth(450) + + layout = QVBoxLayout() + + # Worker-Anzahl Einstellung + worker_group = QGroupBox("ThreadPoolExecutor Einstellungen") + worker_layout = QVBoxLayout() + + worker_label = QLabel("Anzahl paralleler Worker für Transformationen:") + worker_spinbox = QSpinBox() + worker_spinbox.setMinimum(1) + worker_spinbox.setMaximum(32) + worker_spinbox.setValue(app_settings.max_workers) + worker_spinbox.setToolTip("Anzahl der parallelen Worker-Threads für Transformationen (Standard: 8)") + + worker_layout.addWidget(worker_label) + worker_layout.addWidget(worker_spinbox) + worker_group.setLayout(worker_layout) + layout.addWidget(worker_group) + + # SaxonWorkerPool Einstellung + pool_group = QGroupBox("SaxonWorkerPool Einstellungen") + pool_layout = QVBoxLayout() + + pool_checkbox = QCheckBox("SaxonWorkerPool verwenden (empfohlen)") + pool_checkbox.setChecked(app_settings.use_saxon_worker_pool) + pool_checkbox.setToolTip( + "Aktiviert persistente JVM-Prozesse für Saxon-Transformationen.\n" + "Vorteile: Bis zu 10x schneller durch Eliminierung von JVM-Startup-Overhead\n" + "Nachteile: Benötigt JDK (javac) - funktioniert nicht mit JRE allein\n\n" + "Deaktivieren Sie diese Option, wenn:\n" + "• Sie nur ein JRE (keine JDK) installiert haben\n" + "• Sie Probleme mit dem Worker-Pool haben\n" + "• Sie die Funktion testen möchten" ) - if ok and new_workers != current_workers: - app_settings.max_workers = new_workers - app_settings.save() - logger.info(f"max_workers geändert: {current_workers} → {new_workers}") - QMessageBox.information( - self, - "Einstellungen gespeichert", - f"Anzahl paralleler Worker wurde auf {new_workers} gesetzt.\n\n" - f"Die Änderung wird bei der nächsten Transformation wirksam.", - ) + pool_info = QLabel( + "Hinweis: SaxonWorkerPool benötigt ein JDK (Java Development Kit).
" + "Mit JRE allein werden Transformationen im Fallback-Modus ausgeführt.
" + ) + pool_info.setWordWrap(True) + + pool_layout.addWidget(pool_checkbox) + pool_layout.addWidget(pool_info) + pool_group.setLayout(pool_layout) + layout.addWidget(pool_group) + + # OK/Abbrechen Buttons + button_layout = QHBoxLayout() + ok_button = QPushButton("OK") + cancel_button = QPushButton("Abbrechen") + + ok_button.clicked.connect(dialog.accept) + cancel_button.clicked.connect(dialog.reject) + + button_layout.addStretch() + button_layout.addWidget(ok_button) + button_layout.addWidget(cancel_button) + layout.addLayout(button_layout) + + dialog.setLayout(layout) + + # Dialog anzeigen + if dialog.exec() == QDialog.DialogCode.Accepted: + # Speichere Änderungen + current_workers = app_settings.max_workers + current_use_pool = app_settings.use_saxon_worker_pool + + new_workers = worker_spinbox.value() + new_use_pool = pool_checkbox.isChecked() + + changes = [] + + if new_workers != current_workers: + app_settings.max_workers = new_workers + changes.append(f"Worker-Anzahl: {current_workers} → {new_workers}") + logger.info(f"max_workers geändert: {current_workers} → {new_workers}") + + if new_use_pool != current_use_pool: + app_settings.use_saxon_worker_pool = new_use_pool + status = "aktiviert" if new_use_pool else "deaktiviert" + changes.append(f"SaxonWorkerPool: {status}") + logger.info(f"use_saxon_worker_pool geändert: {current_use_pool} → {new_use_pool}") + + if changes: + app_settings.save() + + # Informiere Benutzer über Änderungen + changes_text = "\n".join(f"• {change}" for change in changes) + restart_hint = "" + + if new_use_pool != current_use_pool and self.project: + restart_hint = "\n\nHinweis: Bitte öffnen Sie das Projekt neu, damit die Änderung wirksam wird." + + QMessageBox.information( + self, + "Einstellungen gespeichert", + f"Folgende Einstellungen wurden geändert:\n\n{changes_text}{restart_hint}", + ) def open_existing_project(self, project: Project): """ @@ -744,6 +828,11 @@ class MainWindow(QMainWindow): # Shutdown vorherigen Pool falls vorhanden self._shutdown_saxon_worker_pool() + # Prüfe ob SaxonWorkerPool aktiviert ist + if not app_settings.use_saxon_worker_pool: + logger.info("SaxonWorkerPool deaktiviert - Verwende Fallback-Modus (subprocess)") + return + if not self.project: logger.warning("Kein Projekt geladen, Saxon-Worker-Pool nicht initialisiert") return @@ -777,6 +866,7 @@ class MainWindow(QMainWindow): except Exception as e: logger.error(f"Fehler beim Initialisieren des Saxon-Worker-Pools: {e}") + logger.info("Fallback auf subprocess-Modus") # Kein Pool ist OK - Fallback auf subprocess def _shutdown_saxon_worker_pool(self):