#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;
}
Mittwoch, 14. April 2010
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.
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.
Abonnieren
Posts (Atom)