Habe grade vom Spiegel eine Mail bekommen. Sie geben mir Recht, dass in dem Artikel ein bedeutender Schreibfehler vorhanden war (hatte mich u. a. auch darüber beschwert).
Zitat: "Wir bedauern den ärgerlichen Schriebfehler."
Ich frage mich, wo bleibt bei solch einem Magazin wie dem Spiegel die Qualität? Ich habe mich richtig entschieden, gegen ein weiteres Abo des Spiegels.
Die schweigende Mehrheit in Hessen schweigt weiter. Wagt sich nicht aus der Deckung wie die Verschwörer zur Eroberung der Weltherrschaft. Die schweigende Mehrheit ist die kochsche Wunderwaffe demokratischer Wahlen.
Gestern eine Flug-Ananas von der Elfenbeinküste; eine Ugly aus Jamaika - auch eingeflogen. Heute Mango aus Thailand, ebenfalls frisch eingeflogen. Alle drei sehr lecker.
Zafer Mese, hessisches CDU Mitglied, bei Anne Will: «Roland Koch hat meine Autorität zu Hause untergraben.» Seine Frau hatte nicht CDU gewählt. Das Publikum klatscht und Bosbach grinst blöd. Und ich frage mich: was ist denn das für ein Demokratieverständnis?
Habe gerade nen Knob im Portemonnaie gefunden. Nenne ihn ab sofort Guido.
Lerne grade für eine Prüfung (Alte Geschichte). Da das Ganze manchmal etwas trocken ist, mache ich mir so meine Gedanken:
Kleopatra soll ja nach manchen Quellen in einem Bettsack bzw. in einem Teppich gewickelt in den Palast zu Caesar gelangt sein. Um mir solche Sachen besser zu merken, mache ich mir manchmal kuriose Eselsbrücken ![]()
Nun stelle man sich heute mal vor, unsere Angie wird in einer großen Torte in den Elysee-Palast zu Niko gebracht....
Ich glaube, diese Klamotte vergesse ich nie wieder
Der Spiegel hat sich gegen uns entschieden. Gefühlt nur noch zwischen Nazis und Boulevard wandelnd, verflacht das einstige Sturmgeschütz der Demokratie rasant. Dazu viele Fehler und Unsauberkeiten in Artikeln, bei denen Frau oder ich vom Fach sind.
Gabi schreibt gerade die Kündigung.
Als Held weiss ich, dass das Leben kein zuckerschlecken ist. Täglich U8. Täglich die Achse des Bösen. Da muss der Weg zwischendurch auch mal freigeschossen werden
Was nicht tötet härtet ab. Franz-Josef Wagner war schon nach ein paar Stationen fertig. Weichei.
Mehr U8
Nachtrag: Florian Rötzer greift den verschwurbelten Quatsch von Wagner auf: U-Bahn-Wirklichkeit in der Parallelgesellschaft
Nachtrag 2: Und hier die ganze brutale Wahrheit.
Nachtrag 3: Zypries im Dschungel, kommentiert die Südeutsche Zeitung
- Weltfrieden
- Abgesagt!
- Frau
- Wenn Frau laut wird ist sie stinkig.
- Prioritäten
- Die ARD wird in Zukunft nicht nur bei Klinsmann als Bayern-Trainer eine Sondersendung nach der Tagesschau einschieben. Auch bei Vorstellung einer neuen Putzfrau im Innenministerium und wenn der berühmt Reissack in China umfällt.
- War and peace for Runaways
- Tolstois Schinken komprimiert: Einmal durch die Episodenbeschreibungen der Fernsehzeitungen arbeiten.
Coming soon…
Okay, langsam sind die Signale überzeugend. HD-DVD wird es nicht werden: US-Pornoanbieter will bis spätestens Ende 2008 keine HD DVDs mehr herausbringen.
Die ersten Minuten etwas zäh, dann manchmal etwas polemisch aber keine Minuten
langweilig. Professor Doktor Schachtschneider von der Universität Erlangen zum EU-Vertrag Die Rede auf Youtube, leider zerhackt in 10 Stücke.
OmniFocus ist dann doch nichts anderes als ein etwas netter aussehender Outliner geworden. Und den hat die OmniGroup ja schon im Portfolio. Insofern etwas entäuschend.
OmniFocus ist eine GTD Implementierung für den Mac. Eine ähnliche Idee verfolgt iGTD2. Die erste Version von iGTD habe ich wieder gelöscht. Das Bedienkonzept war mir dann doch zu umständlich.
Eine lokales HBase mit kompletten Hadoop (0.15.1) überlebt auf dem Mac den Ruhezustand nicht. Das gesamte Setup muss herunter gefahren und neu gestartet werden. Nach dem herunter fahren eventuell noch laufende Prozesse mit "kill -9" abgeschiessen.
Nungut, es könnte schlimmer kommen.
Nach «lohnsteuer berlin vordurck» gesucht und exakt die richtige Seite gefunden ![]()
Leider bringt Leopard keine Treiber für den HP LaserJet 1020 mit. Die bei Drucker mitgelieferten Treiber sind nur für die PPC-Plattform ausgelegt gewesen. Rosetta arbeitet nicht auf Treiberebene und auf der Homepage von Hewlett-Packard finden sich nur Treiber für zig Windows-Derivate - Mac wird angeblich nicht unterstützt
Nach kurzer Recherche: hier gibt es Hilfe.
Heute ist Updatetag im SpeexX Blog.
| Frage | Treffer 25. Januar 2005 | Treffer 4. Mai 2006 | Treffer heute |
|---|---|---|---|
| "die erde ist eine scheibe" | ca. 14.100 | ca. 59.100 | ca. 37.800 |
| "die erde ist eine kugel" | ca. 1.260 | ca. 13.400 | ca. 750 |
Dramatische Veränderungen. Aber sehr wissenschaftlich ist das immer noch nicht… Deswegen, liebe Kreationisten, nehmt das weiterhin nicht als Beweis ![]()
Seit JUnit 4 bietet das Framework auch die Möglichkeit parametrisierte Tests. Parametrisierte Test werden auch von TestNG angeboten. Ich finde den JUnit Ansatz angenehmer. Der JUnit Ansatz ist ausschliesslich Quelle-Code orientiert - TestNG bietet auch XML Test-Konfigurationen an. Der TestNG erfordert für meinen Geschmack etwas mehr Tipparbeit.
Der Einstieg für parametrisierte Test in JUnit 4 findet sich im Package org.junit.runners, in der Klasse Parameterized. Die Testklasse muss mit der Annotation @RunWith(org.junit.runners.Parameterized.class) versehen werden. Eine statische Methode mit der Annotation @Parameters liefert eine Java Collection zurück. Die Collection enthält Array-Objekte mit den Parametern. Der JUnit Runner sorgt dafür, dass die Werte der Arrays dem Constructor der Testklasse übergeben werden. Der Constructor muss die gleiche Signatur haben wie die Datentypen des Arrays.
Der Runner erzeugt für jedes Parameter-Array eine neue Instanz der Testklasse. Dann werden die mit @Test annotierten Methoden aufgerufen. Vorteil: anstelle vieler Testmethoden für alle möglichen zu testenden Zustände nur eine Methode mit unterschiedlichen Parametern.
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.Assert.assertEquals;
@RunWith(Parameterized.class)
public class TokenizerTest {
@Parameters
public static Collection
Anmerkung: Der Test ist etwas konstruiert. Der excpected Datentype/Wert ist nicht sinnvoll. int als Datentyp wurde gewählt, um unterschiedliche Datentypen im Constructor zu zeigen. In einer realistischeren Umgebung hätte ich einen String als Datentypen gewählt, der das erwartete Ergebniss darstellt.
Vorgestern in der Kastanienallee. Haus Nummer 86 ist besetzt. An der Fassade in grossen Lettern Kapitalismuskritik. Ich sehe den Kapitalismus durchaus kritisch, halte ihn aber für das Beste, was zur Zeit zu haben ist. Wie viele Wirtschaftsformen vor ihm, wird auch der Kapitalismus sich irgendwann überholt haben. So dämliche und billige Kritik am Kapitalismus habe ich allerdings schon lange nicht mehr gesehen. Vollkommen unreflektiertes Bashing.
Kapitalismus normiert nicht. Gerade der Kapitalismus ermöglicht es immer wieder von der Norm abzuweichen. Normen erzeugen Langeweile - Langweile wie den Trabbie. Langeweile ist für den Kapitalismus tödlich. Und klar, der Kapitalismus zerstört. Aus den Trümmern entsteht neues. Wer dem Kapitalismus so etwas vorwirft, sollte sich dem katholischen Konservatismus hinwenden. Tötet Kapitalismus? Vermutlich weniger als die Sozialisten des letzen Jahrhunderts, Lenin, Stalin, Mao und Hitler mit seinem nationalen Sozialismus.
Vermutlich führen die demokratischen Entscheidungsstrukturen zu einer klassischen Diktatur der Mehrheit ![]()
500.000 Codezeile sind zu beherrschen. Allerdings nicht von einer Person - nicht von zwei Personen. Ich kann das Problem nicht nachvollziehen, welches der Autor hat.
Ich hatte das ganz grosse Glück ein Projekt/Produkt auf der Grünen Wiese zu beginnen. Dabei haben wir von Anfang an darauf geachtet, dass wir keine Code-Blase erzeugen. Wir haben unser Projekt in viele kleine Unterprojekte zerlegt. Jeder Datenbasis wurde als einzelner Service implementiert, als Projekt abgeschottet von den anderen Projekten. Alleine eine Schnittstelle repräsentiert ein solches Unterprojekt - auch die konkrete Implementierung ist ein eigenes Projekt.
In der ersten Phase des Projektes haben wir noch den Fehler gemacht alle abhängigen Bibliotheken im so genannten lib-Ordner des Projektes zu hinterlegen. Es hat sich schnell herausgestellt, dass dies keine gute Idee war. Der Verantwortliche für das Projekt muss immer auf dem Laufenden bei den Abhängigkeiten bleiben. Kommt es zu einem Update, muss er die Abhängigkeiten in seinem Projekt aktualisieren. Gerade bei Projekten, die schnellen Änderungen unterlagen, kamen die Benutzer nicht hinterher und begannen Updates zu ignorieren. Gerade in der Release-Phase führte dies dazu, dass Hektik ausbrach, Schnittstellen und Klassen angepasst werden mussten. Wir haben diese JAR-Hölle sehr schnell abgeschafft.
Als Weg aus dieser Miesere hat sich Maven angeboten. Maven bietet ein einfaches Modell komplexere Abhängigkeiten-Systeme zu verwalten. Durch sein zentrales Repository, welches über das HTTP abgerufen werden kann, ist es sehr pflegeleicht. Wir hatten auch an ein zentrales CVS- oder Filesystem-Repository gedacht, dies aber zugunsten des Maven Ansatz aufgegeben. Als wir den Wechsel auf Maven 1 vollzogen war unser Produkt gerade aus seiner Rüpelphase heraus. Deswegen wurde eines der zentralen Probleme von Maven 1 auch nicht sofort bemerkt: Zwar schleppten wir nicht mehr alle abhängigen Bibliotheken mit uns herum, aber in der zentralen Projekt-Steuerdatei (POM) mussten diese trotzdem gepflegt werden. In Maven kann soetwas zwar durch Vererbung gelöst werden. Dieser Ansatz ist aber nicht sehr elegant, da im schlimmsten Fall der ganze Projektbaum ausgecheckt werden muss. Trotzdem haben wir mit Maven 1 ziemlich gut gelebt.
Nach ca. 2 Jahren mit Maven 1 wurden die Probleme immer akuter. Die Code-Basis war inzwischen auf über 400.000 Zeilen angewachsen (Metrik: reine Anweisungszeilen, ohne Kommentare, Leerzeilen oder Zeilen nur mit schliessenden geschweiften Klammern). Alles zusammen in knapp 4.000 Klassen in über 70 Projekten - über 50 Fremdbibliotheken. Eine solche Modularisierung ist beherrschbar, hängt aber stark von den Werkzeugen ab. Mit Maven 1 lässt sich so etwas definitiv nicht mehr beherrschen. Zum Glück haben dies auch die Macher des Apache Maven Projektes erkannt und mit der Version 2 Abhilfe geschaffen (transitive-Abhängigkeiten). Wir machten uns also daran, das bestehende Maven 1 System durch Maven 2 abzulösen. Keine leichte und schnell durchzuführende Aufgabe. Beide Versionen sind inkompatibel zueinander. Die Umstellung unter dem rollenden Rad der Entwicklung nahm 1 Jahr Zeit in Anspruch. Davon entfielen knapp 11 Monate auf die Planung, der eigentliche Wechsel dauerte dann knapp 1 Monat. Durch die transitiven Abhängigkeiten in Maven 2 wurde deren Pflege für die Projektverantwortlichen radikal vereinfacht. Das parallel eingeführte Continuous Integration (CI) auf Basis von Cruisecontrol führte zu einer starken Verbesserung des gesamten Prozesses.
Bei der Umstellung wurde auch ein radikaler Schnitt gemacht:
- nicht mehr benötigte Projekte wurden im Version-Management System gelöscht
- nicht mehr benötigter Code wurde aus dem System entfernt
Nicht mehr benötigten Code aus zu kommentieren ist übrigens eine weit verbreitete Unsitte. Statt dessen soll er gelöscht werden. Das Versionsverwaltungssystem vergisst es nicht - wem immer das zu Beruhigung dient. Durch die Einführung des CI-Systems sehen wir jetzt sehr schnell, welche Projekte nicht korrekt arbeiten - Projekte mit Fehlern werden nicht gebaut und scheitern komplett. Der Projektverantwortliche ist gezwungen den Fehler zu reparieren.
Mehr Arbeit kommt bei diesem Vorgehen auf das Konfigurationsmanagement zu. Das Maven 2 Repository muss sauber gepflegt werden. Best Practice ist es ein komplett eigenes Repository auf zu bauen. Nicht nur um von ibiblio unabhängig zu sein, sondern für das eigene Abhängigkeitenmanagement. Die Bibliotheken müssen zueinander passen. Gerade bei vielen externen Komponenten ist es nicht ganz einfach diese immer unter einen Hut zu bringen. Die Apache Commons Bibliotheken sind hier ein abschreckendes Beispiel. Restriktiv muss auch die Aufnahme neuer Fremdbibliotheken gesehen werden. Dies darf nur durch die Rolle des Konfigurationsmanagers geschehen.
Das Produkt wächst weiter. Dann werden wird sicherlich in Bereiche vorstossen, die auch mit den aktuellen Werkzeugen nicht zu beherrschen sind. Ich bin gespannt was dann kommt.
500.000 Codezeilen zu beherrschen ist möglich. Allerdings nicht in einem einzigen Projekt. Auch nicht in zwei oder drei Projekten. Ein solches Vorgehen ist für mich heute ein Anti-Pattern.
Neben JMX ist das Concurrent API ein echtes Highlight in Java 5. Letzte Woche habe ich ein wenig mit den Möglichkeiten gespielt. Dabei habe ich festgestellt, dass nicht immer alles so funktioniert wie es sollte. Ich meine damit nicht das API selbst, sondern eine der Aufgaben, die ich ausprobieren wollte. Eine der Aufgaben war es auf einem String Buchstaben zu zählen. Auf die Buchstaben wurde mittels charAt(int) zugegriffen. Damit beide Prozessoren des MacBook pros ausgenutzt werden habe ich den String geteilt und jedes Callable hat sich einen Teil des Strings vorgeknöpft und den Buchstaben 'e' gezählt.
Motivation
Der beschrieben Code stellt ausschliesslich ein Beispiel da die Packages aus java.util.concurrent zu verwenden. Das Beispiel ist nicht besonders sinnhaft. In einer ersten Implementierung habe ich auch im Bereich auf Fertigstellung warten einen Fehler gemacht. Es wurde permanent auf das Ergebnis gepollt. Dies führte mitunter zu katastrophalen Laufzeitverhalten. Erst mit der Implementierung des waiter Objektes und einem delay zwischen dem pollen der Ergebnise verbesserte sich das Laufzeitverhalten merklich. Deswegen eignet sich die unten beschriebene Implementierung vermutlich auch nicht für devide and conquer-Probleme. Hierfür müsste ein forkjoin Framework geschaffen werden. Aus den Changelogs des JSR 166 geht hervor, dass ein solches Framework für Java 7 geplant ist.
Testumgebung
Hardware und Betriebssystem
- MacBook pro, 15"
Intel Core Duo, 1.83 GHz, 2 GB RAM, 2 MB L2-Cache, 667 MHz Bus, Java 5
Anmerkung: Nicht in Auswertung aufgenommen, da Hardware nicht vergleichbar. - Intel(R) Pentium(R) D CPU 3.40GHz, Dual Core, 4 GB RAM
CentOS-5, Linux version 2.6.18-8.1.8.el5PAE (mockbuild@builder4.centos.org) (gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)) - Intel Xeon CPU, 2.40GHz, Quad Core, 4 GB RAM
CentOS-5, Linux version 2.6.18-8.1.15.el5PAE (gcc version 4.1.1 20070105 (Red Hat 4.1.1-52))
Java Virtual Machines
Java 5
- Sun Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_09-b03)
- BEA JRockit(R) (build R26.4.0-63-63688-1.5.0_06-20060626-2259-linux-ia32, )
- IBM IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Linux x86-32 j9vmxi3223-20060504 (JIT enabled)
- Apple Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-237)
Anmerkung: Nicht in Auswertung aufgenommen, da Hardware nicht vergleichbar.
Java 6
- Sun Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
- BEA JRockit(R) (build R27.4.0-90-89592-1.6.0_02-20070928-1715-linux-ia32, compiled mode)
- IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4 Linux x86-32 jvmxi3260-20071121_15015 (JIT enabled)
Testprogramm
Das Testprogramm ist als Attachment angehängt.
Ergebniss
Alle Messwerte können in der angehängten Excel-Datei eingesehen werden.
Erklärung
Single steht für einen Single Prozessor Testlauf. Ein Kern wir ausgelastet.
Dual steht für einen Dual Prozessor Testlauf. Zwei Kerne werden ausgelastet.
Zahlenangaben Zeit in Millisekunden. Kleinerer Wert gleich besserer Wert.
Anmerkung
Aus den Ergebnissen geht nicht hervor, dass die IBM JVM für Java 5 extrem lange für die ersten Durchläufe benötigt. Der JIT greift erst beim 2 oder 3 Lauf. Vorher ist das Laufzeitverhalten katastrophal, 111632 Millesekunden beispielsweise fuer den Single Run. Im Vergleich, die Sun JVM für Java 5 erledigt den gleichen Job in 4326 Millisekunden. Das ist 25 mal schneller.
Der Garbage Collector hat minimale Auswirkungen auf das Testprogramm. Deswegen sind die Performanzmessungen nicht zu verallgemeinern.

![Darth Steilmann [FRAU MIT DARTH VADER MASKE]](http://www.speexx.de/blog/images/2008/01/darth%20steilmann.small.jpg)
![Müll in der Schönleinstraße / Berlin Kreuzberg [MÜLLHAUFEN]](http://www.speexx.de/blog/images/2008/01/schoenleinstrasse.jpg)
![Rotschopf [ROTE HAARE, WEIT AUSGEFÄCHERT]](http://www.speexx.de/blog/images/2008/01/redhead.small.jpg)