Google Music im Praxiseinsatz
Google Music bewährt sich bei mir gerade. Der Monitor meines Haupt-PCs (mit der Musik darauf) flackert und ich will gerade keinen neuen holen, schreibe ich die Arbeit eben am Laptop fertig. Doch meine Musik will ich natürlich trotzdem hören. Statt da jetzt beide Rechner anzuhaben und mit dem einen nur Musik abzuspielen ist die Musik ja sowieso im Internet, also hör ich sie jetzt im Browser.
Genau der Anwendungsfall, für den der Dienst wohl mal gedacht war.
Nebenbei kann ich so berichten, dass die Aussetzer, die ich anfangs beobachten konnte, nicht mehr auftraten.
Google, jetzt fehlt nur noch HTML 5. Damit ich den Flashplayer wieder runterwerfen kann.
Arbeit
Eine wissenschaftliche Arbeit zu schreiben ist eine seltsame Erfahrung. Kaum nutzt man ein paar Quellen und baut Formeln ein sieht der Text von vorher fast schön aus. Formeln können schön sein, wenn sie erklären was man vorher nur benutzt hat und den Text in eine echte Arbeit verwandeln. Formale Definitionen fühlen sich so an, als würde man etwas wirklich deutlich erklären. Da stehe ich etwas staunend vor meiner eigenen Wahrnehmung.
Wahrscheinlich gefällt das dem Programmierer in mir. Was vorher nur Struktur war wird langsam befüllt und was durch Quellen belegt ist, sieht nicht mehr unfertig aus. Der Spaghetticode wurde zur elegant gelösten und alle Testfälle erfüllenden fertigen Funktion. Einen Text schreiben und Programmieren sei ja sowieso sehr ähnlich. Das konnte ich früher nie nachvollziehen, jetzt doch ein bisschen.
Und auch das drumrum hat Ähnlichkeiten. Die wirkliche Arbeit an der Arbeit fühlt sich ganz ähnlich an wie die Woche, die man dem Projekt widmet das endlich zuende gedacht wurde und nun angegangen werden kann. Dann werden auf einmal Vorräte für den nächsten Tag gleich miteingekauft. Damit man nicht raus muss, wenn es nicht sein muss. Und es ist nur um 2 Uhr nachts die Zeit und der Wille da, noch etwas hier reinzuschreiben.
APUs integriert
Obwohl der Hardwareempfehler möglichst automatisch ablaufen soll, sind manchmal manuelle Anpassungen nötig. So kamen die APUs in die Hardwaredatenbank, also Prozessoren mit integrierter Grafikkarte. Und es passierte prompt, was nicht passieren sollte: Die Prozessoren wurden manchmal mit Grafikkarten kombiniert, die schlechter waren als die integrierten. Ich habe jetzt Code eingebaut, das zu verhindern, bei der momentanen Empfehlung für 150€ sieht man das ganz gut:
Wattrechner
Bin gerade gefragt worden, ob ein 450-Watt Netzteil für einen Core2Duo plus einer 6000er-Radeon ausreicht. Ohne den Rechner anzuhaben steht man dann erstmal da und schätzt ab. Den Rechner anzuhaben hilft aber auf die Schnelle auch nicht so viel, auf der Herstellerseite findet man auch keine genauen Angaben zum Stromverbrauch. Also, abschätzen per Checkliste:
- Das Netzteil kann normalerweise die Leistung auf der Packung nicht dauerhaft leisten. Selbst wenn es ein gutes ist eher 80% davon. Und selbst das lässt außer acht, dass die verschiedenen Schienen des Netzteils unterschiedlich belastbar sind und wann es im besten Wirkungsgrad läuft. Aber als grobe Schätzung: Netzteilleistung * 0.8
- Die CPU verbraucht bis zu etwas mehr als 100 Watt. Bei einem Dual Core kann man mit deutlich weniger rechnen. Aber wenn man keine Ahnung von der Cpu hat, sind 120 eine gute Maximalabschätzung.
- Die GPU kann deutlich mehr verbrauchen. Durch den PCI-Express-Port selbst kommen bis zu 75 Watt, die meisten Grafikkarten wollen aber noch Zusatzstecker, die jeweils nochmal 75 Watt zuführen können (über die bei Wikipedia erwähnten 150-Watt-Stecker bin ich bei Gpus noch nicht gestolpert). Eine 6870 von oben als Beispiel mit ihren zwei Zusatzsteckern hat demanch ein theoretisches Maximum bei 3 * 75 = 225 Watt.
- Dazu kommen die Lüfter plus den Laufwerken. Laufwerk# * 20 sollte genug Luft für die Lüfter lassen
In dem Fall eben hatte die Grafikkarte wohl nur einen Stecker, also 150 Watt, ohne die Cpu nachgeguckt zu haben sind das bei 2 Laufwerken also 150 (Gpu) + 100 (Cpu) + 60 (Laufwerke)=310, das Netzteil liefert 450 * 0.8=360, das kann also knapp funktionieren.
Hat man dann einen Rechner zur Hand und etwas Ruhe, kann man auch einen solchen Stromverbrauchrechner nehmen.
Java: Externe Programme starten
Ich mag ja Bash. Auch, weil man dort einfach alles kombinieren kann, was auf dem System liegt. Bei echten Sprachen wie Java geht das dann plötzlich nicht mehr so einfach, bei Java ist es sogar besonders kompliziert.
Aufrufen
Der Aufruf selbst ist gar nicht so ganz absurd. Lässt man das Fangen der Exceptions weg sieht es so aus:
Process child = Runtime.getRuntime().exec(command); child.waitFor();
Ein eigener Prozess mit dem Systembefehl wird gestartet, auf den dann gewartet wird. Nur reicht das nicht.
Ausgabe fangen
Mit obigem Code läuft der Prozess eine Weile und stirbt dann. Denn es müssen die Ausgaben abgefangen werden. Das ist zwar völlig bescheuert und ich wollte es erst auch nicht glauben, aber es ist wirklich so. Dann sieht es so aus:
Process child = Runtime.getRuntime().exec(command); StreamGobbler errorGobbler = new StreamGobbler(child.getErrorStream(), "ERROR"); StreamGobbler outputGobbler = new StreamGobbler(child.getInputStream(), "OUTPUT"); errorGobbler.start(); outputGobbler.start(); child.waitFor();
StreamGobbler ist dabei eine von Java World kopierte Klasse, die nichts anderes macht als in einem Thread die Ausgaben zu fangen:
class StreamGobbler extends Thread { InputStream is; String type; StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; } public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = null; while ( (line = br.readLine()) != null) { System.out.println(type + ">" + line); } } catch (IOException ioe) { ioe.printStackTrace(); } } }
Java: Simpler Map-Cache mit Lebenszeit
Bei mir waren es SQLite-Datenbankabfragen, die zu lange dauerten. Nach dem Neubau von pc-kombo war die Seite dadurch erstmal langsamer als vorher. Das lag aber nicht wirklich an der neuen Architektur oder Datenbank an sich, sondern dass durch nicht übernommene Optimierungen weniger direkt im Speicher behalten wurde. Also musste ein Cache her.
Ich will hier als Beispiel zeigen, wie man so etwas aufbauen kann. Anmerkungen zum Code sind gern gesehen. So sind mir im cacheControl-Thread beim Schreiben dieses Eintrags direkt ein paar Logikfehler aufgefallen, die ich jetzt korrigiert habe. War wohl ungenügend getestet...
Ein Singleton, eine Hashmap und einen Thread zum Aufräumen abgelaufener Cacheeinträge, mehr braucht es eigentlich nicht. Beliebige Objekte werden hereingegeben, Strings als ids, zurückgegebene Objekte muss die darüberliegende Programmmlogik casten.
Beispielnutzung
try { return (Vector<Gpu>) Cache.getInstance().get("Warehouse:Gpus"); } catch (CacheIdNotFoundException cinfe) { Vector<Gpu> gpus = Database.getInstance().getGpus(); Cache.getInstance().put("Warehouse:Gpus", gpus.clone(), 3600*24L); return gpus; }
Implementierung
Cache.java:
import java.util.HashMap; import java.util.Map; import java.util.TreeMap; public class Cache { private static Cache instance = new Cache(); private Cache() { Thread cacheControl = new Thread(new Runnable() { public void run() { while(true) { try { Thread.sleep(3600); } catch (InterruptedException ie) { } long now = System.currentTimeMillis() / 1000L; Long time = null; String key = ""; while ((time = ttl.floorKey(now)) != null) { key = ttl.get(time); cache.remove(key); ttl.remove(time); } } } }); cacheControl.start(); } public static Cache getInstance() { return instance; } /** * The memory-cache */ private Map<String, Object> cache = new HashMap<String, Object>(256); /** * moment-to-die for the values corresponding to the given keys */ private TreeMap<Long, String> ttl = new TreeMap<Long, String>(); /** * Put an objekt in the cache * @param key * @param value * @param seconds Time to live */ public void put(String key, Object value, Long seconds) { long now = System.currentTimeMillis() / 1000L; cache.put(key, value); ttl.put(now + seconds, key); } /** * Get a value from the cache * @param key * @return * @throws CacheIdNotFoundException if key not found */ public Object get(String key) throws CacheIdNotFoundException { Object value = cache.get(key); if (value == null) { throw new CacheIdNotFoundException(); } else { return value; } } }
Die CacheIdNotFoundException.java ist natürlich witzlos:
class CacheIdNotFoundException extends Exception {}
Google Music
Das letzte Bild war ein Bild des Beginns des Scanvorgangs des Google Music Managers. Die Idee des Dienstes fand ich ja ziemlich gut, damals hatte ich es aber noch nicht getestet. Dank Bernds Einladung hat sich das nun geändert. Meine Eindrücke bisher.
Upload stinkt
Das Bild war direkt vom Beginn des Uploads. Und der läuft immer noch. Um etwas genauer zu sein: Es ist etwa ein Fünftel hochgeladen. Meine Musiksammlung ist nicht riesig und meine Leitung DSL 6000, also auch nicht riesig, aber auch nicht furchtbar klein. Gut, nachts ist der PC aus, das beschleunigt den Vorgang nicht gerade. Aber angenehm ist was anderes. Warum nicht die Dinger hashen und alle direkt bereitstellen, die schon von anderen Nutzern hochgeladen wurden? Das wäre furchtbar einfach, da sowieso ein Desktopprogramm genutzt wird.
Besonders nervig wird der Upload, da man unter Linux bei jedem Login in den Manager ein Einmalpasswort erstellen muss, wenn Googles 2-Faktor-Anmeldung genutzt wird. Was ich tue.
Flash erforderlich
Ich habe an mehreren Stellen gelesen, dass HTML 5 genutzt werden würde. Was teilweise stimmt, Doctype ist html. Trotzdem begrüßt mich diese Meldung:
Was soll das denn? Da hat trotz allem Codecwirrwarr Youtube eine Beta für HTML5-Videos, aber das meines Wissens problemlos .ogg und mp3 unterstützende Audio-Element wird nicht genutzt, nichtmal als Option oder Fallback? Nur ärgerlich.
Oberfläche brauchbar
Ich möchte hier nicht stärker werten. Dafür fehlt etwas Zeit mit dem Dienst. Aber bisher macht die Oberfläche einen guten Eindruck, problemlos können Alben von Musikern angezeigt oder nur Alben durchsucht und abgespielt werden. Wobei die Abspielfunktion seltsam im Menü versteckt ist, das hätte ich anders gemacht. Aber gerade verglichen mit Grooveshark ist der Eindruck der Oberfläche gut, nicht weil Grooveshark so chaotisch wäre, sondern weil die Oberfläche dort so träge ist. Nicht so hier.
Vorzüge des Desktop-Players fehlen
Teilweise gewöhnt man sich doch sehr an seine Software. Ich mag Amarok. Gut, es gibt auch wenig Gründe, auf den nun zu verzichten. Aber es wäre doch gut, wenn das ginge. Derzeit ist dem nicht so:
- Globale Hotkeys für Webanwendungen sind wohl Zukunftsmusik
- Unter Last stockte die Musik zu schnell (oder der Buffer war leer)
Beides ist unangenehm. Nett wäre es, wenn man über ein cachendes Amarokplugin auf gmusic zugreifen könnte.
Mit ein paar Verbesserungen könnte durch gmusic irgendwann die eigene Sammlung vielleicht wirklich primär in der Cloud liegen. Was doch ein gutes vorläufiges Fazit ist.
PS: 2 Einladungen sind frei 1 Einladung ist noch frei.