"Hallo, ich bin raichoo und ich habe ein MacBook". Das sind Sätze mit denen man in vielen Kreisen schnell Freunde finden kann (Vorsicht Ironie!). Aber mal ehrlich, in den letzten Tagen kann man sich besonders schöne Kommentare gefallen lassen. Mein Favorit ist hier "Apfelnazi" (Goodwin's Law lässt grüßen). Die Diskussionskultur lässt hier ziemlich zu wünschen übrig, wer Leute nach dem Betriebssystem beurteilt hat in meinen Augen doch eher einen massiven Schaden.
Aber was bewegt die Leute dazu so zu reagieren? Auf der einen Seite mag das ganze auf einem pseudoelitären Gefühl basieren. Apple ist Mainstream. Gegen Mainstream sein ist rebellisch, cool und was weiß ich noch alles. Ich bin ja selber keine Ausnahme, meine Lebensweise ist sicherlich nicht die eines Ottonormalverbrauchers. Aber diese extremen Anfeindungen gehen doch echt schon zu weit.
Doch zurück zu den Beweggründen. Wikileaks ist im Moment sicherlich ein sehr bewegendes Thema, und das Verhalten vieler Firmen wie Visa, Paypal, Mastercard und auch Apple ist nicht nur verwerflich, es ist in meinen Augen auch undemokratisch.
Was also machen? Boykottieren? Guter Plan, Boykott war immer schon die wirksamste Waffe des Verbrauchers, denkt man sich. Die Problematik die sich hieraus aber ergibt ist folgende: der überwiegende Großteil der Firmen wird so reagieren. Ein bisschen Druck vom Staat eventuell noch ein paar Zuwendungen unter der Hand und schon wird der Stecker gezogen. Unsere Freiheit wird also potentiell von jeder Firma beschnitten die nur den nötigen Einfluss hat, oben genannte Beispiele befinden sich nur gerade in dieser Situation besonders in so einer Position. Man kann sich also praktisch totboykottieren, der Hydra wachsen die Köpfe einfach nach.
Wie also reagieren? Alle Apple Produkte aus dem Fenster werfen in den nächsten Mediamarkt rennen, ein Plastikwaffeleisen kaufen das nach einem Jahr auseinanderfällt und Ubuntu installieren? Ich sag es ehrlich: Linux ist derzeit einfach technisch keine Alternative für mich, und FreeBSD's Treibersituation auf Notebooks ist auch nicht wirklich berauschend. Windows mag ich nicht, usw.. Erreicht wird damit doch praktisch eh nichts. In meinen Augen ist beim Thema Wikileaks das effektivste Mittel doch eh: so hartnäckig spenden wie es nur geht. Wege dafür gibt es genug. Unterstützung ist weitaus mächtiger als Boykott.
Wenn mir also jemand ein Notebook mit 13" Formfaktor, 6 Stunden+ Akkulaufzeit, Alugehäuse, großen Touchpad auf dem mindestens ein FreeBSD rennt (damit meine ich das ALLE Komponenten auch zuverlässige Treiber haben) und das dazu auch noch KEINERLEI Komponenten von irgendeiner Firma enthält die irgendwo mal Scheisse gebaut hat zeigen kann, bring it on. (Das ist ernst gemeint, würde mich interessieren ob es da draußen irgendwas gibt was dem auch nur ansatzweise entspricht)
Samstag, 25. Dezember 2010
Montag, 20. September 2010
Scala: Klassen erweitern mal anders
Datentypen erweitern ist mehr oder weniger etwas das man des öfteren machen muss, und das ist nicht umbedingt immer unproblematisch. Nehmen wir mal an wir hätten folgende Klasse:
Ganz klar: hochkomplizierter Code.
wir Objekte dieser Klasse in unserem Code nahtlos verwenden können. Diese Methode nennen wir
Jetzt gibt es verschiedene Wege wie wir diese Methode in
Eine Lösung ist hier ziemlich elegant mit Traits, Selftyping und Structural Types zu machen.
Als erstes definieren wir einen Structural Type der eine genaue Schnittstelle definiert. Wir nennen ihn
Was wir jetzt brauchen ist unsere generalisierte Implementation von
Wie man sieht muss der muss der Typparameter
Alles was wir jetzt noch machen müssen ist das Trait
Das ganze Zeit mal wieder wie extrem mächtig das Scala Typsystem ist und was für elegante Features die Sprache zum lösen immer wiederkehrender Probleme bietet. Ich hoffe dieses Beispiel gibt euch eine kleine Idee was man damit machen kann. ;)
class Test(val x: Int)
Ganz klar: hochkomplizierter Code.
Test
quillt an Features nur so über, aber uns fehlt gerade eine Methode damitwir Objekte dieser Klasse in unserem Code nahtlos verwenden können. Diese Methode nennen wir
bla
. Das Problem ist allerdings: Wir haben den Code von Test
nicht und können ihn deswegen nicht um bla erweitern.Jetzt gibt es verschiedene Wege wie wir diese Methode in
Test
einbinden könnten. Der offensichtlichste ist sicherlich Vererbung. Blöd ist nur: Wir haben bla
schon geschrieben und würden ihn ungern duplizieren, vor allem weil wir den Code bereits schön generalisiert haben.Eine Lösung ist hier ziemlich elegant mit Traits, Selftyping und Structural Types zu machen.
Als erstes definieren wir einen Structural Type der eine genaue Schnittstelle definiert. Wir nennen ihn
xAble
und er macht nichts weiter als zu definieren das alle Klassen die eine Methode x
anbieten vom Typ xAble
sind.
type xAble = { def x: Int }
Was wir jetzt brauchen ist unsere generalisierte Implementation von
bla
. Hier verwenden wir, Selftyping. Das ist ein Feature das es uns erlaubt innerhalb eines Traits so zu tun als wäre es von einem bestimmten Typ ohne davon zu erben.
trait Gimme[A <: xAble] {
self: A =>
def bla(): Unit = println(self.x + 1)
}
Wie man sieht muss der muss der Typparameter
A
ein Subtyp von xAble
sein, also die methode x
liefern.Alles was wir jetzt noch machen müssen ist das Trait
Gimme
in das Objekt des Typs Test
zu mischen und wir haben das ganze um bla
erweitert.
object Main {
class Test(val x: Int)
type xAble = { def x: Int }
trait Gimme[A <: xAble] {
self: A =>
def bla(): Unit = println(self.x + 1)
}
def main(args: Array[String]): Unit = {
val t = new Test(666) with Gimme[Test]
t.bla()
}
}
Das ganze Zeit mal wieder wie extrem mächtig das Scala Typsystem ist und was für elegante Features die Sprache zum lösen immer wiederkehrender Probleme bietet. Ich hoffe dieses Beispiel gibt euch eine kleine Idee was man damit machen kann. ;)
Donnerstag, 24. Juni 2010
FreeBSD 8.1 und die JVM
Alios hat gerade seinen Server auf den neusten Stand gebracht und prompt funktionierte Sakura natürlich wieder nicht. Das Problem war das die JVM wohl anscheinen den IPv6 Stack genommen hat und sich damit nicht verträgt, ein Workaround ist die JVM einfach dazu zu zwingen den IPv4 Stack zu nehmen. Das geht mit der
Wenn euch also das nächste mal ein Socket beim Connect aus unerfindlichen Gründen abraucht, versucht es mal damit.
-Djava.net.preferIPv4Stack=true
Option.Wenn euch also das nächste mal ein Socket beim Connect aus unerfindlichen Gründen abraucht, versucht es mal damit.
Montag, 21. Juni 2010
Spass mit Scala Infixtypen
In Scala gibt es das interessante Konzept der Infix Typen, dabei handelt es sich um nichts weiter als Typen die zwei Parameter erwarten. Scala erlaubt hier Infix Notation.
Damit eröffnen sich interessante Möglichkeiten des Typsystems, z.B: "Operatoren" aus Typen erstellen die wiederum Typen erstellen. Verwirrt? In Scala gibt es bereits
Ziemlich cool, jetzt kann man sich Operatoren basteln die Typen erstellen und sich anfühlen wie native Features der Sprache :)
object Main {
class FooBar[A, B]
def main(args: Array[String]): Unit = {
//zwei unterschiedliche Schreibweisen die das gleiche
//meinen
var x: FooBar[Int, BigInt] = null
var y: Int FooBar BigInt = null
}
}
Damit eröffnen sich interessante Möglichkeiten des Typsystems, z.B: "Operatoren" aus Typen erstellen die wiederum Typen erstellen. Verwirrt? In Scala gibt es bereits
=:=,
<:<
und <%<
, diese Konstrukte kann man sich unter anderem auch selbst zusammenbasteln, im folgenden Beispiel bauen wir uns einen <@@@<
"Operator"
abstract class <@@@<[A, B] extends (A => B)
class Test[T <: (Int => Int)]
object Main {
def main(args: Array[String]) = {
val t = new Test[Int <@@@< Int]
}
}
Ziemlich cool, jetzt kann man sich Operatoren basteln die Typen erstellen und sich anfühlen wie native Features der Sprache :)
Mittwoch, 2. Juni 2010
Paralleles Primzahlsieb in Scala
Nach der Präsentation von Google Go habe ich mich gefragt ob man das parallele Primzahlsieb auch in Scala so machen kann. Ich muss sagen das ich das Resultat sogar einfacher und eleganter finde als die Go Implementation. Sicherlich gibt es performantere Algorithmen aber hier geht es einfach um das Prinzip zu zeigen wie einfach man Parallelisieren kann.
HINWEIS: Das Programm terminiert nicht, da für jede Primzahl ein eigener "Thread" (Actors die per react warten verhalten sich nicht ganz so wie Threads die in einem Loop warten, sondern sind leichtgewichtiger) gestartet wird und diese weiter auf Futter warten. Es ist auf jeden Fall möglich das das ganze anhält, ich will lediglich das Prinzip zeigen und das Beispiel nicht unnötig aufblasen.
HINWEIS: Das Programm terminiert nicht, da für jede Primzahl ein eigener "Thread" (Actors die per react warten verhalten sich nicht ganz so wie Threads die in einem Loop warten, sondern sind leichtgewichtiger) gestartet wird und diese weiter auf Futter warten. Es ist auf jeden Fall möglich das das ganze anhält, ich will lediglich das Prinzip zeigen und das Beispiel nicht unnötig aufblasen.
import scala.actors.Actor
import scala.actors.Actor._
class Prime(value: Int) extends Actor {
var next: Option[Prime] = None
println(value)
start
def act(): Unit = loop {
react {
case x: Int if ((x % value) != 0) =>
next match {
case Some(p: Prime) => p ! x
case None => next = Some(new Prime(x))
}
}
}
}
object Main {
def main(args: Array[String]): Unit = {
val primer = new Prime(2)
3 to args(0).toInt map (primer ! _)
}
}
Montag, 10. Mai 2010
Mergesort in Scala
Und aus der Kategorie "Sortieren für Besessene" kommt heute mal wieder ein Beispiel, aber ausnahmsweise kein Quicksort ;)
Was ich besonders toll an diesem Beispiel finde ist das auf gleich 2 Listen gleichzeitig gematcht wird wie es auch in Haskell geht. Da hat Scala mal wieder richtig Spass gemacht.
Was ich besonders toll an diesem Beispiel finde ist das auf gleich 2 Listen gleichzeitig gematcht wird wie es auch in Haskell geht. Da hat Scala mal wieder richtig Spass gemacht.
object Main {
def merge[T <% Ordered[T]](l: List[T], r: List[T]): List[T] =
(l,r) match {
case (x::xs, y::ys) => if (x < y)
x::(merge(xs, r))
else
y::(merge(l, ys))
case (xs, Nil) => xs
case (Nil, ys) => ys
}
def mergesort[T <% Ordered[T]](list: List[T]): List[T] =
if (list.length > 1) {
val (l, r) = list splitAt (list length)/2
merge(mergesort(l), mergesort(r))
} else list
def main(args: Array[String]): Unit = {
println(mergesort(List(4,5,9,1,2,4,5,9,8,7)))
}
}
Samstag, 8. Mai 2010
Samstag, 17. April 2010
Git-Mode für die KSH
Ich habe gerade mal meine Git Erweiterung für die Kornshell in meinen Bitbucket gestellt. Das ganze liegt zwar noch unter "Mercurial-Integration" aber sollte zu finden sein ;). Wie schon beim Mercurial mode wechselt man mit
mode git
in den entsprechenden Modus. Die Farbe der Commit ID wechselt von Rot (uncommited changes) zu Gelb (nicht die aktuellste Revision) zu Grün (aktuellste Revision und nichts zu commiten). Außerdem wird der aktuelle Branch angezeigt und im Falle eines "detached HEAD" Zustands visuell gewarnt. Viel Spass damit!Git happens
Ich bin kein besonders großer Fan von Git, allerdings kommt man hin und wieder einfach nicht drum herum. Da mein Standard-Workflow derzeit einfach darin besteht Commits im Nirvana verschwinden zu lassen gibt es eigentlich nur 2 Alternativen für mich:
Zweiteres klang bei näherer Betrachtung einfach attraktiver.
Da ich im privaten Umfeld mehr Mercurial nutze platzt meine
Beispiel:
Die beiden Aliase sind nicht besonders spektakulär aber nützlich:
Ein weiteres Alias reproduziert das verhalten von
Das alles hilft aber noch nicht bei meinem eigentlichen Problem: Commits schrotten.
Hierfür habe ich mir eine kleine Erweiterung geschrieben… Also nicht zum schrotten, sondern zum wiederherstellen ^^.
Mit
Für mich sind das ein paar sehr brauchbare Anpassungen, ich hoffe der ein oder andere findet sie ebenso brauchbar :)
- Eine Selbsthilfegruppe für Git-Geschädigte aufsuchen
- Ein paar Skripten schreiben die mir das Leben leichter machen
Zweiteres klang bei näherer Betrachtung einfach attraktiver.
Da ich im privaten Umfeld mehr Mercurial nutze platzt meine
.gitconfig
derzeit durch Aliase auseinander die meinen Workflow erhalten, 2 davon replizieren in etwa das Verhalten von incoming
und outgoing
, oder anders gesagt: sie zeigen mir eingehende bzw. ausstehende Commits an.Beispiel:
// commits die noch nicht in origin/master
// eingeflossen sind
git out origin/master
// commit aus origin/master die noch nicht
// in meinem lokalen Branch liegen
git in origin/master
Die beiden Aliase sind nicht besonders spektakulär aber nützlich:
out = "log --stat HEAD --not"
in = "!f() { git log --stat $1 --not HEAD; }; f"
Ein weiteres Alias reproduziert das verhalten von
hg log -G
und zeigt mit die History in einem halbwegs lesbaren Graphen an (bei komplexeren Bäumen greife ich aber lieber zu einem Tool wie GitX)
graph = "log --graph --pretty=oneline --abbrev-commit --decorate --all"
Das alles hilft aber noch nicht bei meinem eigentlichen Problem: Commits schrotten.
Hierfür habe ich mir eine kleine Erweiterung geschrieben… Also nicht zum schrotten, sondern zum wiederherstellen ^^.
Mit
git orphans
werden mir sogenannte "dangling commits" angezeigt, das sind Commits die auf normalem Wege nicht mehr erreichbar sind. Da git ohne Garbage Collection (git gc
oder git prune
) nicht so ohne weiteres Commits wegwirft sondern als "dangling commits" im Nirvana vorhält, kann ich mit git reset --hard SHA1
(oder in meinem Fall mit dem Alias git rollback SHA1
) meinen HEAD auf gerade verlorene Commits umbiegen und alles ist wieder beim Alten. git orphans
verifiziert Commitobjekte und zeigt mir den dazugehören History Eintrag an. Das Ganze ist ein simples Shellskript das man einfach zu den anderen git Kommandos (welche bei mir in libexec/git-core liegen) unter dem Namen git-orphans
abglegt.
#!/bin/sh
USAGE=''
OPTIONS_SPEC=
. git-sh-setup
if [ "$#" != "0" ]
then
usage
fi
git fsck --lost-found |
while read dangling type sha1
do
case "$type" in
commit)
if git rev-parse -q --verify "$sha1" >/dev/null
then
git log --color -n 1 "$sha1"
echo ""
fi
;;
esac
done | git_pager
Für mich sind das ein paar sehr brauchbare Anpassungen, ich hoffe der ein oder andere findet sie ebenso brauchbar :)
Mittwoch, 14. April 2010
C++ "Lazy Evaluation" für Streams
Manchmal will man nicht das ein Stream überhaupt Sachen ausgibt (z.B. für Debugstreams die sich bei Bedarf zuschalten kann) und dann will man natürlich auch nicht das die Parameter die durch den Streamoperator gehen abgearbeitet werden da sich dort eventuell komplexe Parsereien verstecken könnten.
Hierfür gibt es einen denkbar einfachen Trick mit C-Macros (jaja ich weiß, aber hin und wieder bin sogar ich da pragmatisch :P ).
In diesem Code wird nichts ausgegeben und auch nichts ausgewertet, das Verhalten lässt sich einfach zur Laufzeit ändern. Tada! "Lazy Evaluation" on demand :)
Hierfür gibt es einen denkbar einfachen Trick mit C-Macros (jaja ich weiß, aber hin und wieder bin sogar ich da pragmatisch :P ).
#include <iostream>
#define DEBUGSTREAM if (!debug); else std::cerr
int main() {
bool debug = false;
DEBUGSTREAM << "Test\n";
return 0;
}
In diesem Code wird nichts ausgegeben und auch nichts ausgewertet, das Verhalten lässt sich einfach zur Laufzeit ändern. Tada! "Lazy Evaluation" on demand :)
C++ Steams dressieren
Manchmal möchte man gerne bestimmte Aktionen auslösen die sich nach dem Abwickeln einer Streambefüllung zutragen sollen (z.B. das ein Lock freigeben). Hier ist ein kleiner Trick der genau das macht und in bestimmten Situationen durchaus hilfreich sein kann: wenn z.B. man durch widrige Umstände nicht in der Lage ist den Scope zu begrenzen.
#include <iostream>
#include <tr1/memory>
class Tester {
public:
Tester& operator<<(std::string s) {
std::cout << s;
return *this;
}
~Tester() {
std::cout << "End\n";
}
};
std::tr1::shared_ptr<Tester> wrapper() {
std::cout << "Begin\n";
return std::tr1::shared_ptr<Tester>(new Tester());
}
int main() {
*(wrapper()) << "A "<< "test!\n";
std::cout << "Ending scope\n";
return 0;
}
Deadlocks jagen mit DTrace
Deadlocks gehören so ziemlich zu den widerlichsten Phänomenen die man sich so beim Programmieren vorstellen kann. Vor allem wenn sie nur sporadisch auftreten. Irgendein Thread weigert sich einfach ein Lock wieder freizugeben und wir hängen. Mit dem gleichen Problem durfte ich mich neulich auch rumschlagen, leider tappten wir total im Dunkeln da nicht lokalisieren war wer das Lock eigentlich in Beschlag genommen hat. Hier musste wieder mal meine Lieblingswunderwaffe ran und das Problem mit einem D Skript eingekreist werden.
Was dieses Skript macht ist nichts anderes als sich zu jedem Lock der geschlossen wird den Stacktrace zu merken und sobald wir an den Punkt kommen an dem das Deadlock auftritt uns zu zeigen wer gerade das Lock hält das uns am weitergehen hindert. Das ganze ist ein unglaublicher Speicherfresser (ich muss dazu sagen das die jeweiligen Stacktraces einfach nur abnorm waren) da ich hier Speculations verwende (siehe letzter Eintrag ;) ) und DTrace bereinigt den Speicher nur in bestimmten Intervallen, was in bei der Menge an Locks einfach zu langsam war. Außerdem hat man nur eine begrenzte Anzahl an Speculations zur Verfügung. Aber DTrace wär nicht das was es ist wenn man das nicht auch "aushebeln" könnte ;)
Also, ohne weitere Umschweife: der Star des gestrigen Tages!
Was dieses Skript macht ist nichts anderes als sich zu jedem Lock der geschlossen wird den Stacktrace zu merken und sobald wir an den Punkt kommen an dem das Deadlock auftritt uns zu zeigen wer gerade das Lock hält das uns am weitergehen hindert. Das ganze ist ein unglaublicher Speicherfresser (ich muss dazu sagen das die jeweiligen Stacktraces einfach nur abnorm waren) da ich hier Speculations verwende (siehe letzter Eintrag ;) ) und DTrace bereinigt den Speicher nur in bestimmten Intervallen, was in bei der Menge an Locks einfach zu langsam war. Außerdem hat man nur eine begrenzte Anzahl an Speculations zur Verfügung. Aber DTrace wär nicht das was es ist wenn man das nicht auch "aushebeln" könnte ;)
nspec
dient dazu die Anzahl der möglichen Speculations hochzusetzen und cleanrate
bestimmt die Frequenz der Garbagecollection, mit -b
schrauben wir den Gesamtpuffer auf 128MB hoch.Also, ohne weitere Umschweife: der Star des gestrigen Tages!
#!/usr/sbin/dtrace -b 128m -x nspec=20 -x cleanrate=101 -s
pid$target::deadlockgoeshere:entry
{
self->traceme = 1;
}
pid$target::deadlockgoeshere:return
/self->traceme/
{
self->traceme = 0;
}
pid$target::pthread_mutex_lock:entry
/spec[arg0] == 0/
{
spec[arg0] = speculation();
speculate(spec[arg0]);
ustack();
}
pid$target::pthread_mutex_lock:entry
/spec[arg0] && self->traceme/
{
commit(spec[arg0]);
spec[arg0] = 0;
}
pid$target::pthread_mutex_lock:entry
/spec[arg0] && self->traceme == 0/
{
discard(spec[arg0]);
spec[arg0] = 0;
}
pid$target::pthread_mutex_unlock:entry
{
discard(spec[arg0]);
spec[arg0] = 0;
}
Dienstag, 30. März 2010
Spekulatives Tracen mit DTrace
Spekulieren ist ja nicht erst seit der "Finanzkrise" der letzte Schrei, auch wir Programmierer stehen hin und wieder mal vor der Situation das wir Kram anhäufen von dem wir nicht wissen ob wir ihn später noch gebrauchen können. Besonders beim Debuggen fallen oft Daten an bei denen wir erst wissen ob sie interessant sind wenn wir schon bis zum Hals in Messwerten stecken. Wie also die Spreu vom Weizen trennen? DTrace hat ein Feature das leider viel zu wenig Beachtung bekommt: Speculations.
Ein einfaches Beispiel: Wir interessieren uns für alles was im Kernel während des Öffnens einer Datei passiert, allerdings wollen wir das Ergebnis nur wissen wenn das Öffnen fehlschlägt. Das macht folgendes D-Script:
Ok, gehen wir das Ganze mal durch:
Um in einer Klausel das "Aufzeichnen" zu starten reicht ein
ACHTUNG: Puffer zu füllen ist eine kostspielige Angelegenheit, denkt daran das wir uns hier im Kernelkontext befinden. Also solltet ihr Daten die ihr nicht mehr braucht auch sofort verwerfen. Wachsen eure Puffer ungehindert weiter wird die DTrace VM euch einen Strich durch die Rechnung ziehen und selbst anfangen Daten zu verwerfen damit ihr das System nicht in den Abgrund zieht. Des weiteren ist der Trace den ich oben beschrieben habe auch schon recht "brutal" da der Puffer mit einem kompletten
Ein einfaches Beispiel: Wir interessieren uns für alles was im Kernel während des Öffnens einer Datei passiert, allerdings wollen wir das Ergebnis nur wissen wenn das Öffnen fehlschlägt. Das macht folgendes D-Script:
#!/usr/sbin/dtrace -s
syscall::open:entry
/execname == "a.out"/ {
self->spec = speculation();
speculate(self->spec);
printf("%s",copyinstr(arg0));
}
fbt:::
/self->spec/ {
speculate(self->spec);
}
syscall::open:return
/self->spec && arg1 == -1/ {
commit(self->spec);
}
syscall::open:return
/self->spec/ {
discard(self->spec);
}
Ok, gehen wir das Ganze mal durch:
self->spec = speculation();
legt threadlokal einen Puffer unter dem Namen spec
an. Eine Speculation ist also nichts anderes als ein Puffer in dem wir Messwerte zwischenspeichern und darauf warten ob sie wichtig werden.Um in einer Klausel das "Aufzeichnen" zu starten reicht ein
speculate(self->spec)
, alle darauf folgenden Messwerte wandern in unseren Puffer. Tritt ein Ereignis ein das unseren Werten im Puffer Bedeutung verleiht können wir sie mit commit(self->spec);
ausgeben oder im gegenteiligen Fall mit discard(self->spec);
verwerfen.ACHTUNG: Puffer zu füllen ist eine kostspielige Angelegenheit, denkt daran das wir uns hier im Kernelkontext befinden. Also solltet ihr Daten die ihr nicht mehr braucht auch sofort verwerfen. Wachsen eure Puffer ungehindert weiter wird die DTrace VM euch einen Strich durch die Rechnung ziehen und selbst anfangen Daten zu verwerfen damit ihr das System nicht in den Abgrund zieht. Des weiteren ist der Trace den ich oben beschrieben habe auch schon recht "brutal" da der Puffer mit einem kompletten
fbt
Messdatensatz befüllt wird. Das bremst open-systemcalls übel aus, also: HANDLE WITH CARE!
Dienstag, 16. März 2010
Ganz viel DTrace :D
Heute war ein ziemlich voller Tag. Ich habe unter anderem meinen Vortrag über DTrace den ich schon einmal in der warpzone gegeben habe bei der Mac User Group Gütersloh gehalten. Ich hab versucht dieses doch sehr technische Thema möglichst einfach rüber zu bringen da die Folien eigentlich eher für ein sehr technophiles Publikum gedacht waren. Hoffe ihr habt trotzdem Spass daran ;)
Für alle die was auf die Ohren wollen hatte ich die Ehre eine Sendung mit Mario Heide von Pofacs zu machen. Also: die volle Dröhung DTrace :D
Für alle die was auf die Ohren wollen hatte ich die Ehre eine Sendung mit Mario Heide von Pofacs zu machen. Also: die volle Dröhung DTrace :D
Montag, 22. Februar 2010
Quicksort in Scala
Ich weiß, ich weiß. Nicht schon wieder ein Quicksort. Dem ein oder anderen wird es sicher schon zur Nase rausquillen, aber generische Quicksort Algorithmen sind wirklich ein guter Weg um eine neue Sprachen kennenzulernen (zumindest empfinde ich das so ^^) Dieser hier ist mit ein wenig Hilfe zustande gekommen. Warum ist das ganze überhaupt wert gepostet zu werden? Erstmal ist Scala eine sehr interessante Sprache die den Versuch unternimmt FP und OOP zu vereinen (ohne dabei in das Kitchen-Sink Muster zu verfallen), des weiteren läuft sie auf der JVM was einem die Möglichkeit gibt auf den reichhaltigen Fundus an Java-Libs zurückzugreifen und die Vorzüge der JVM zu nutzen. Spannende Sprache für alle die mal was ganz anderes sehen wollen ;)
object Main {
def qs[T <% Ordered[T]](list: List[T]): List[T] =
list match {
case Nil => Nil
case x::xs => {
val (l, g) = xs partition (_ < x)
qs(l) ++ (x::qs(g))
}
}
def main(args: Array[String]): Unit = {
val a = List(5,3,2,1,7,8,9,4,6)
println(qs(a))
}
}
Montag, 1. Februar 2010
Bitbucket Repository für Codeschnipsel
Ich werde immer mal wieder nach Config-Files oder Codeschnipseln gefragt die ich dann meistens auf meinen Blog stelle. Diese sind aber dank von Blogspot schwer bis gar nicht lesbar, also habe ich sie einfach mal auf Bitbucket geschoben. Dann haben alle was davon ;)
Viel Spass beim rumspielen. Ich hoffe ihr könnt was damit anfangen und habt vielleicht den ein oder anderen Verbesserungsvorschlag.
UPDATE: Links aktualisiert
hg clone https://raichoo@bitbucket.org/raichoo/ksh-mercurial-integration/
Viel Spass beim rumspielen. Ich hoffe ihr könnt was damit anfangen und habt vielleicht den ein oder anderen Verbesserungsvorschlag.
UPDATE: Links aktualisiert
KSH93: Mercurial Promptmode
Nach dem großartigen Blogeintrag von Steve Losh und seinem ZSH-Mercurial Prompt habe ich mir gedacht: "Ok, das geht auch mit der KSH". Ich verfolge allerdings einen etwas anderen Ansatz. Anstatt das meine Shell bei jedem Kommando selbst überprüft ob sie in einem Repository ist (zuviel Overhead meines Erachtens nach) habe ich unterschiedliche Modes definiert (ksh für "shell" und hg für "mercurial") zwischen denen ich mit
Der Prompt färbt sich rot wenn sich der Status verändert hat und zeigt mir neben der Revisionsnummer auch noch den Namen das Branches an auf dem ich gerade bin :)
Das ist jetzt die erste Version. Mal sehen wie sich das gute Stück noch weiterentwickelt :)
UPDATE: Hab den Code noch mal um einiges verbessert.
mode
wechseln kann.Der Prompt färbt sich rot wenn sich der Status verändert hat und zeigt mir neben der Revisionsnummer auch noch den Namen das Branches an auf dem ich gerade bin :)
_checkrevision() {
set -A HGOUTPUT $(hg id -n -b -t 2> /dev/null)
if [[ ${HGOUTPUT[0]} != "" ]]
then
if grep '+' <(echo ${HGOUTPUT[0]}) > \
/dev/null 2> /dev/null
then
print ":${BOLD}${RED}${HGOUTPUT[0]}${NORM}\
@${CYAN}${HGOUTPUT[1]}${NORM}" && return
elif grep -v 'tip' <(echo ${HGOUTPUT[*]}) > \
/dev/null 2> /dev/null
then
print ":${BOLD}${YELLOW}${HGOUTPUT[0]}${NORM}\
@${CYAN}${HGOUTPUT[1]}${NORM}"\
&& return
else
print ":${BOLD}${GREEN}${HGOUTPUT[0]}${NORM}\
@${CYAN}${HGOUTPUT[1]}${NORM}"\
&& return
fi
fi
}
mode() {
if [[ $1 == 'ksh' ]]
then
export PS1='${NORM}\[${USERCOL}${USER}${NORM}\@\
${HOSTCOL}${HOSTNAME}${NORM}\:${BLUE}$(_checkdir)\
${NORM}]\:${RED}${HISTCMD}${NORM}\> '
elif [[ $1 == 'hg' ]]
then
export PS1='${PURPLE}☿${NORM}$(_checkrevision)> '
fi
}
Das ist jetzt die erste Version. Mal sehen wie sich das gute Stück noch weiterentwickelt :)
UPDATE: Hab den Code noch mal um einiges verbessert.
Montag, 4. Januar 2010
Quicksort in Python
Und einfach nochmal weils so schön ist:
Und die Ersties bei mir an der Uni beschweren sich darüber das sie funktionale Programmierung lernen müssen -_-
UPDATE: Das ganze geht noch schöner mit Python List Comprehensions
def partition(f, a):
l = []
r = []
for i in a:
if f(i):
l.append(i)
else:
r.append(i)
return l,r
def qs(a):
if a == []:
return a
return qs([x for x in a[1:] if x < a[0]]) \
+ [a[0]] + \
qs([x for x in a[1:] if x >= a[0]])
def qs2(a):
if a == []:
return a
l,g = partition(lambda x: x < a[0], a[1:])
return qs2(l) + [a[0]] + qs2(g)
a = [4,6,3,5,1,2,7,0,9,8]
print qs(a)
print qs2(a)
Und die Ersties bei mir an der Uni beschweren sich darüber das sie funktionale Programmierung lernen müssen -_-
UPDATE: Das ganze geht noch schöner mit Python List Comprehensions
Ein Hauch von Python
Ich spiele ja in letzter Zeit sehr viel mit Ruby und Python herum. Was mir an Python besonders gefällt sind unter anderem Generatoren. Damit kann man schöne Sachen machen.
Einen ähnlichen Effekt kann man unter Ruby mit Enumeratoren hinkriegen
Ich gebe zu das ich hier ziemlich geschummelt habe und Python Generatoren über das hinausgehen was ich hier in Ruby zeige. Aber es kann hin und wieder mal recht praktisch sein ;)
def test():
for i in range(0,3):
yield i
x = test()
for i in x:
print i
Einen ähnlichen Effekt kann man unter Ruby mit Enumeratoren hinkriegen
class Test
def each
if block_given?
for i in 0...3
yield i
end
else
Enumerator.new(self)
end
end
end
t = Test.new
e = t.each
for i in e
puts i
end
Ich gebe zu das ich hier ziemlich geschummelt habe und Python Generatoren über das hinausgehen was ich hier in Ruby zeige. Aber es kann hin und wieder mal recht praktisch sein ;)
Quicksort in Ruby
Angestachelt vom Alios' kurzer Illustration von Quicksort in Haskell hab ich mir mal überlegt ob man das gleiche auch in Ruby 1.9 so schreiben kann. Man kann ;)
Ich finde das ganze zeigt sehr eindrucksvoll wie mächtig moderne Sprachen sind die OOP und FP vereinen. Prinzipiell kann man das Ding auch twittern :P (darum die kurzen Namen)
UPDATE: Da konnte man noch etwas verkürzen ^^
UPDATE 2: Für alle denen 2 Array Durchläufe mit find_all zuviel sind gibts hier auch noch eine etwas nettere Version ;)
def qs(a)
return a if a == []
(qs a.drop(1).find_all{|x| x < a[0]}) \
+ [a[0]] + \
(qs a.drop(1).find_all{|x| x >= a[0]})
end
Ich finde das ganze zeigt sehr eindrucksvoll wie mächtig moderne Sprachen sind die OOP und FP vereinen. Prinzipiell kann man das Ding auch twittern :P (darum die kurzen Namen)
UPDATE: Da konnte man noch etwas verkürzen ^^
UPDATE 2: Für alle denen 2 Array Durchläufe mit find_all zuviel sind gibts hier auch noch eine etwas nettere Version ;)
def qs(a)
return a if a.empty?
l, g = a.drop(1).partition{|x| x < a[0]}
(qs l) + [a[0]] + (qs g)
end
Abonnieren
Posts (Atom)