ich muß sehr große Dateien (>1 GB) nach beliebigen Kriterien sortieren, daher fallen interne Sortierverfahren wie Quicksort/Heapsort gleich weg.
Bei externen Sortierverfahren gibt es - wenn man der gängigen Literatur glauben darf - 2 Ansätze: Den externen Mergesort und den externen Distributionsort, die sich fast invers zueinander verhalten.
Zu beiden Verfahren gibt es dann wieder unterschiedliche Optimierungsstrategien, wie etwa [Knuth]
MergeSort -> Replacement Selection
DistSort -> Random Cycling
Meine Frage ist nun, ob ein Ansatz prinzipielle Vorteile gegenüber dem anderen bringt. Oder ist es egal, welchen von beiden ich implementiere? Einen direkten Vergleich beider konnte ich leider nicht finden.
Um aussagekräftige Zeiten zu erhalten, habe ich ein paar Testmethoden geschrieben um eine große Textdatei einzulesen.
Was mir dabei aufgefallen ist und mich leicht rätseln lässt, ist die schnelle Verarbeitung:
Ich habe eine 850MB große Textdatei, welche ich blockweise einlese und dann auf Zeilen aufsplitte. Als Alibifunktion merke ich mir ein bestimmtes Zeichen jeder Zeile, einfach um zu gewährleisten, dass jede Zeile einmal benutzt wurde.
Für diese Datei benötigt ein Durchlauf nun durchschnittlich 2,7 Sekunden. Ich lasse den Test 10 mal durchlaufen und schmeiße die Extremwerte weg um Initialisierungsspitzen zu vermeiden. Auch der Taskmanager mit Gelesene E/A-Bytes an, dass die Datei vollends gelesen wurde.
Einfache Rechnung 850 MB / 2,7 Sekunden = 314 MB/s.
Es handelt sich dabei um einen neuen Quad-Rechner mit SATA-Anschluß, aber sollte dies nicht über der sequentiellen Maximalleistung einer modernen (Nicht-SSD) Festplatte liegen?
Nicht dass mich das schnelle Lesen nicht freut, ich würde nur gerne verstehen, wie er zustande kommt
Was habe ich schon versucht?
Ich lese die Datei mit einem StreamReader ein, und speichere jede Zeile in einer ArrayListe
Hier könnte es schneller sein, die Datei in größeren Blöcken (Stichwort: FileStream.Read) einzulesen, statt immer zeilenweise vorzugehen .
Pro gelesenem Block kannst du dann mehrere Zeilen so wie von den anderen beschrieben extrahieren und gehashed speichern.
In dem Zusammenhang wäre es auch möglich die Datei asynchron einzulesen. Dies führt laut Literatur zu einer besseren Auslastung der Festplatte, aber ob dies für deinen Fall wirklich Sinn macht, ist fraglich.
Zitat von Barbara
(Vom RAM her sollte es kein Problem sein, da ich 3,5 Gigabyte zur Verfügung habe)
Das ist leider nicht pauschal auslegbar. In einem 32 Bit-OS stehen dir nur 2GB für dein Anwendungsprogramm zur Verfügung. Der virtuelle Adressraum beträgt zwar 4GB, aber 2GB davon sind quasi für das Betriebssystem reserviert. Allerdings gibt es noch einen Schalter um 3GB zu nutzen (Stichwörter: PAE, /3GB)
Erst mit einem 64 Bit-OS ist diese Beschränkung sehr weit nach oben verlegt worden.
Es gab vor längere Zeit (glaube Ende letzten Jahres) einen Bericht über einen managed Kernel von den nächsten Windows-Versionen. Die Entwickler/-Chefs von Windows weigern sich aber grundlegend von ihren C-Anwedungen und teils C++ abzutreten.
Nur schade, dass nicht reines C#, sondern extra Cspec dafür eingeführt werden mußte. Daraus könnte man nun ableiten, dass C# an sich nicht ohne Erweiterung für höheres ausreicht.
Frage zum integrierten Unit-Testing in VS2008/NUnit:
Sind damit auch Performance-Tests möglich?
Also Möglichkeiten zur genauen Zeitmessung von Funktionen oder eine Auslastungskurve des Speichers.
Bislang habe ich in der Doku zu NUnit nur Möglichkeiten für die Verifikation von Methoden gefunden. Dies ist zwar der eigentliche Sinn von Unit-Tests, aber trotzdem wären Performancetests auch beizeiten wichtig und nützlich.
Wenn dies mit NUnit nicht möglich ist, gibt es vielleicht Alternativen dazu, die diese Art von Tests beherrschen?
Je nach Dateikodierung öffne ich die Textdateien entweder per Standard- (Codepage: 1252) oder Unicode-Kodierung (Codepage: 1200).
Bei normaler Kodierung steht der Teststring in einer neuen Zeile am Ende der Textdatei.Bei Unicode-Kodierung steht vor dem String noch ein nicht druckbares Zeichen.
Dieses Verhalten ist nicht gewünscht und ich möchte - wenn es möglich ist - vermeiden, eine Sonderbehandlung für Unicode einzuführen.
Gibt es vielleicht eine gleichbleibende und darum empfehlenswertere Methode des StreamWriters um an das Dateiende zu schreiben?
Ich habe gelesen, dass es bei Unicode kein EOF-Tag gibt, wie bei Textdateien üblich. Hat dies damit etwas zu tun?
Also ich freue mich auf den bestimmt gut dokumentierten Programmcode, auch wenn mir persönlich eine Umsetzung mit WCF sympathischer gewesen wäre.
Da du Lager- und Artikelverwaltung als Beispiele angibst, wirst du bestimmt auch eine datenbankneutrale Datenhaltung zur Verfügung stellen.
Welche Methodik/Vorgehensweise wirst du dafür benutzen, weil bei dem Thema scheiden sich ja die Geister?
In Verbindung mit Kapitel 5 kannst du einmal einen Service für zentrale Programmeinstellungen oder auch einen Service für immer wiederkehrende Dateioperationen erstellen.
Irgendwo im Programm hast du dann beispielsweise folgenden Code:
PropertyService prop = (PropertyService) ServiceManager.Services.GetService(typeof(PropertyService));
String con = prop.GetProperty("ApplicationConnectionString");
Naja, für richtig kurios halte ich den Fehler nicht.
Schließlich wird bei OneWay -Kommunikation nur in eine Richtung kommuniziert, da sollte die Verbindung nicht ewig offen gehalten werden. Hier wird näher darauf eingegangen.
Darum würde wohl auch eine Erhöhung der Timeout-Zeit nicht helfen, vielleicht braucht die Operation auf einem alten Rechner 8x so lange
Wie wäre es, wenn dein Programm eine Timeout-Exception richtiggehend erwartet und dies dann halt nur zu einer Neuinstanzierung des Proxys führt.
Laut MSDN soll bei jedem WCF-Aufruf gewisse Exceptions immer erwartet werden, siehe hier
Aber nun stellt sich eine andere Frage bezüglich Errorhandling bei WCF:
Jeder Zugriff auf den Proxyclient muß von ziemlich vielen catch-Klauseln begleitet werden, was bei vielen Funktionen ja furchtbar unübersichtlich wird.
beim Ausführen von svcutil.exe, auch komplett ohne Parameter, kommt folgender Fehler:
C:\>svcutil
Unbehandelte Ausnahme: System.IO.FileLoadException: Die Datei oder Assembly svcu
til, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a oder eine
Abhängigkeit davon wurde nicht gefunden. Fehler bei der Strong Name-Überprüfung
. (Ausnahme von HRESULT: 0x8013141A)
Dateiname: svcutil, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d
50a3a ---> System.Security.SecurityException: Fehler bei der Strong Name-Überprü
fung. (Ausnahme von HRESULT: 0x8013141A)
Die Zone der Assembly, bei der ein Fehler aufgetreten ist:
MyComputer
Bei einer WCF-Applikation, die per wsHTTPBinding kommuniziert, werden Exceptions und Faults nicht vom Server an den Client zurückgeliefert.
Stattdessen wird beim manuellen Werfen einer FaultException gemeldet, dass keine Fehlerbehandlungsroutine dafür vorhanden ist.
Ich benutze quasi eine 08/15-Konfigurationsdatei.
Laut einem Artikel könnte es daran liegen, dass beim wsHTTPBinding standardmäßig OneWay gesetzt ist. Also einseitige Kommunikation.
Aber muß ich nun zur sinnvollen Fehlerbehandlung gleich komplett auf Duplex oder Async-Kommunikation umsteigen?
Verwirrend finde ich auch, dass in den ganzen WCF-Beispielen die man so findet, davon eigentlich nie die Rede ist.
Ich versuche die Frage mal allgemeiner zu formulieren:
Ich habe auf dem Server nun eine temporäre Zertifikatsstelle und mit dieser ein gültiges Serverzertifikat erstellt. Dieses befindet sich auch im Zertifikatsspeicher des Servers.
Welche prinzipiellen Schritte sind nun auf dem Client auszuführen?
Für dein Szenario, wo verschiedene Anforderungen bestehen, ist WCF recht gut geeignet.
Größter Nachteil sind die Betriebssystem-Vorraussetzungen, solange dies kein Problem darstellt, spricht nichts gegen WCF.
Also alles ab XP, Server 2003 und natürlich Vista.
Bei WCF gibt es Sessions, die einen Client während einer längeren Sitzung identifizieren können.
ich möchte Zertifikate zur Authentifizierung einsetzen um Benutzer bei einer Serverapplikation zu erkennen. Diese Anwendung soll über das Internet funktionieren, wodurch leider die praktische Windows-Authentifizierung entfällt.
Ausgegangen bin ich von diesem Tutorial, welches wohl nur die Minimalanforderungen an eine zertifikatsbasierte Anwendung erfüllt, aber für den Einstieg sollte das genügen: UserNamePassword Validator
Um schon mal im vorhinein alle Probleme mit einer offiziellen Zertifizierungsstelle zu vermeiden wird beim Server der Wert
Mein erstes Verständnisproblem tritt nun schon auf, bei der Frage was beim Client zu tun ist.
Für den Zertifikatsteil wird im MSDN-Artikel folgendes Batch-Skript gelistet:
echo ************
echo Server cert setup starting
echo %SERVER_NAME%
echo ************
echo making server cert
echo ************
makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Der erste Befehl erzeugt augenscheinlich das Zertifikat selber und legt es in diesen ominösen PC-Speicher für Zertifikate.
Der zweite Befehl ist dagegen Voodoo. Laut Beschreibung
Zitat
The following lines in the Setup.bat batch file copy the server certificate into the client trusted people store.
soll dies das Zertifikat am Client installieren. Aber der Client ist ein anderer PC, aber die Adresse des Clients wird nirgends angegeben.
Wenn ich den Server starte und mir mit dem svcutil.exe die WCF-Clientsettings generieren lasse, wird sogar ein Eintrag für das erstellte Zertifikat hinzugefügt:
Trotzdem kommt bei der ersten Verbindung Client->Server der in diesem Forum schon öfters erwähnte Fehler:
Zitat
Fehler beim Aufbau der X509-Zertifikatkette (CN=pc_wo_server_laueft). Die Vertrauenskette des verwendeten Zertifikats kann nicht verifiziert werden. Ersetzen Sie das Zertifikat, oder ändern Sie den Zertifikatprüfungsmodus. Eine Zertifikatskette wurde zwar verarbeitet, endete jedoch mit einem Stammzertifikat, das beim Vertrauensanbieter nicht als vertrauenswürdig gilt.
Muß ich zuvor das Zertifikat beim Server exportieren und per Zertifikats-SnapIn irgendwie installieren? Davon steht jedenfalls im MSDN-Artikel nichts...
In der eingebetteten Exception steht dann aber sogar der genaue Grund:
The service certificate is not provided. Specify a service certificate in ServiceCredentials.
Source: CreateServerX509TokenProvider()
Nur ich habe meines Wissens nirgends etwas eingestellt, was ein X.509-Zertifikat nötig machen würde.
Muß man dies vielleicht irgendwo explizit ausschalten oder kann man die ClientCredentials bei MessageClientCredentialType=UserName nur per Zertifikat mitgeben?
Sehr, sehr komplex die Authentifizierungsmöglichkeiten mit WCF.
Für den Fall, dass der derselbe Benutzer auf den beiden PCs unterschiedliche Passwörter hat. Dann lasse ich das Passwort am Client einlesen und würde es gerne zur automatischen Windowszertifizierung verwenden.
Nur wie setze ich die Windows-Credentials. Die Eigenschaft ClientCredentials in der Proxy-Klasse bietet ja jede Menge Möglichkeiten zum Setzen von Namen/Passwörtern.
Die offensichtlichste Variante hat zumindest bei mir nicht funktioniert, der Client wurde trotzdem abgewiesen.
Genauergesagt funktioniert es für den angemeldeten Benutzer, wenn dieser ein anderes Passwort besitzt. Möchte man sich jedoch mit einem Benutzer anmelden, der auf dem Klient-PC nicht läuft, dann ist dies nicht möglich.
In meiner bisherigen Architektur war der Zugriffsclient statisch im ganzen Clientprogramm vorhanden und daher habe ich immer versucht mit der bestehenden Instanz weiterzuarbeiten.
in einem WCF-Szenario kommuniziere ich ganz mit WCF. In der Applikation gibt es nun eine Login-Maske, wobei auch ein späteres Ausloggen möglich ist.
Ich schließe beim Logout den Kanal mit der Close()-Methode wonach sich der Kanal im Zustand Closed befindet.
Nur wie kann ich den Kanal dann wieder öffnen? Bei einem nachträglichen Open() kommt die Meldung, dass der Kanal verworfen wurde:
"Auf das verworfene Objekt kann nicht zugegriffen werden.\r\nObjektname: System.ServiceModel.ChannelFactory`1[IUserManager]."
Momentan muß ich die Anwendung immer komplett neu starten, was sicherlich nicht Sinn der Sache sein kann.
Dies ist ganz ähnlich, wenn ein Fehler im Kanal auftritt, wie etwa ein Kommunikationsfehler. Dann geht der Kanal ist den Zustand Faulted. Mit der Abort()-Methode bekomme ich ihn dann auch in den Closed-Zustand, aber halt nicht mehr wieder auf.
Ich hab jetzt ganz nach deinem Tipp einen BindingContext ohne jegliche Sicherheit hinzugefügt und schon dauert die Anmeldephase vom Client keine ganze Sekunde mehr.
Ich habe mal die Diagnosemethoden von WCF konfiguriert, aber ehrlichgesagt werde ich von den Darstellungen des Service Trace Viewers regelrecht erschlagen.
Ist poste trotzdem mal die Stelle, die wohl 12s benötigt, auch wenn ich nicht raussehe für was.
Der Sprung ist zu sehen von 15:17 + 10s auf 15:17 + 22 Sekunden.
Der erste Verbindungsaufbau zwischen zwei PCs die im gleichen LAN sind, dauert nun etwa ab 10 Sekunden, im Durchschnitt etwa 14 Sekunden.
Pings zwischen beiden Rechern haben eine Laufzeit von <1 Millisekunden.
Nach dem ersten Aufbau der Verbindung wird jeder Zugriff dagegen zeitnah ausgeführt, was auch wunderbar ist.
Nur wieso dauert der Verbindungsaufbau derart lange, werden zu Beginn so viele Steuer- und Metadaten ausgetauscht?
Ich habe probeweise mal das netTCP-Binding zur Kommunikation bemüht, dort war aber das gleiche Verhalten zu beobachten. Die Verbindung brauchte immer noch mehr als 8 Sekunden zum Aufbau.
Im realen Einsatz ist diese Zeitspanne verkraftbar, aber zum Testen ist es wirklich sehr hindernd, wenn man ständig so lange warten muß.
Gibt es darum vielleicht eine Möglichkeit zumindest im Debugmodus eine schnellere Verbindung hinzubekommen?
Bei einem Dienst (Service1) wurde die App.config immer richtig erweitert bei Benutzung des Merge-Flags. Nun werden alte <serviceModel>-Einträge anscheinend ignoriert und jedesmal neue Einträge hinzugefügt.
Ist zwar nicht weltbewegend, wollte ich deswegen hier nur erwähnt haben.
Habt ihr besondere Strategien entwickelt um die Client-Konfigurationen zu benutzen. Eventuell nicht in die allgemeine App.config mitaufnehmen sondern extra lagern?
ich lasse einen Dienst mit WCF (Framework 3.5) hosten.
myHost = new ServiceHost(typeof(UserService);
myHost.Open();
In der App.config stehen die nötigen Hosting-Details.
Nun möchte ich einen zweiten Service hosten lassen, welcher fachlich nichts mit dem anderen zu tun hat und darum nicht in eine gemeinsame Schnittstelle gepresst werden soll, z.B. ganz abstrus einen AutobahnService.
Wie ist hierbei vorzugehen?
Ich gehe mal davon aus, dass in der Konfigurationsdatei mehrere <service></service> Einträge problemlos funktionieren. Aber wie gehe ich programmtechnisch vor, weil doch die Klasse ServiceHost im Konstruktor nur einen Typen erwartet.