<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<channel>
	<title>The Software Developer &#187; Tools</title>
	<atom:link href="http://blog.hachmeister.org/category/tools/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.hachmeister.org</link>
	<description></description>
	<pubDate>Thu, 04 Jun 2009 16:11:53 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Java Profiling</title>
		<link>http://blog.hachmeister.org/2009/03/java-profiling/</link>
		<comments>http://blog.hachmeister.org/2009/03/java-profiling/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 20:08:12 +0000</pubDate>
		<dc:creator>Karsten</dc:creator>
		
		<category><![CDATA[Tools]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[profiler]]></category>

		<guid isPermaLink="false">http://blog.hachmeister.org/?p=43</guid>
		<description><![CDATA[Geschwindigkeit spielt in vielen Bereichen eine entscheidende Rolle. Um nicht raten zu müssen, ob eine neue Implementierung eines Problems schneller abgearbeitet wird, sollte jeder professionell vorgehende Softwareentwickler einen Profiler nutzen. 
Ein einfach einzusetzender Profiler ist The Java Interactive Profiler.
Alles was dafür gebraucht wird ist die profile.jar Datei und eine profile.properties Datei, wie in folgendem Beispiel:
profiler=on
file=profile.txt
Bei [...]]]></description>
			<content:encoded><![CDATA[<p>Geschwindigkeit spielt in vielen Bereichen eine entscheidende Rolle. Um nicht raten zu müssen, ob eine neue Implementierung eines Problems schneller abgearbeitet wird, sollte jeder professionell vorgehende Softwareentwickler einen Profiler nutzen. <span id="more-43"></span></p>
<p>Ein einfach einzusetzender Profiler ist <a href="http://jiprof.sourceforge.net/">The Java Interactive Profiler</a>.</p>
<p>Alles was dafür gebraucht wird ist die profile.jar Datei und eine profile.properties Datei, wie in folgendem Beispiel:</p>
<pre>profiler=on
file=profile.txt</pre>
<p>Bei dem Start des zu testenden Java Programms müssen nur 2 Parameter mit angegeben werden:</p>
<pre>-javaagent:profile.jar -Dprofile.properties=profile.properties</pre>
<p>Anschließend findet man in dem aktuellen Verzeichnis eine profile.txt Datei, in der die Auswertung zu finden ist.</p>
<p>Am Besten kann man dieses an einem Beispiel sehen. In einer sortierten Liste versuchen wir einen zufällig erzeugten Wert zu finden, zuerst mit einer einfachen Iteration über das gesamte Array.</p>
<pre class="prettyprint lang-java">public class JIProfilerTest {

    private static int maxRandom = 10000000;

    private int count = 1000000;

    private int[] nums;

    public static void main(String[] args) {
        Random random = new Random(System.currentTimeMillis());

        JIProfilerTest test = new JIProfilerTest();
        test.init(random);

        int numsFound = 0;

        for (int i = 0; i &lt; 10000; i++) {
            int number = random.nextInt(maxRandom) + 1;

            if (test.search(number) &gt; -1) {
                numsFound++;
            }
        }

        System.out.println(numsFound + " Nummern gefunden.");
    }

    private void init(Random random) {
        nums = new int[count];

        for (int i = 0; i &lt; count; i++) {
            nums[i] = random.nextInt(maxRandom);
        }

        Arrays.sort(nums);
    }

     private int search(int number) {
        for (int i = 0; i &lt; nums.length; i++) {
            if (number == nums[i]) {
                return i;
            }
        }

        return -1;
    }

}</pre>
<p>Lässt man das oben angezeigt Programm ausführen, erhält man eine profile.txt Datei mit folgendem Inhalt.</p>
<pre>+----------------------------------------------------------------------
|  File: profile.txt
|  Date: 2009.03.04 20:44:32 PM
+----------------------------------------------------------------------

+------------------------------
| Thread depth limit: Unlimited
+------------------------------
+------------------------------
| Thread: 1
+------------------------------
              Time            Percent   
       ----------------- ---------------
 Count    Total      Net   Total     Net  Location
 =====    =====      ===   =====     ===  =========
     1  32923,1    293,8   100,0     0,9  +--JIProfilerTest:main    (jiprof)
     1      0,2      0,2     0,0          | +--JIProfilerTest:&lt;init&gt;    (jiprof)
     1    732,4    732,4     2,2     2,2  | +--JIProfilerTest:init    (jiprof)
 10000  31896,8  31896,8    96,9    96,9  | +--JIProfilerTest:search    (jiprof)

+--------------------------------------
| Most expensive methods (by net time)
| Frame Count Limit: Unlimited
+--------------------------------------

               Net
          ------------
 Count     Time    Pct  Location
 =====     ====    ===  ========
 10000  31896,8   96,9  jiprof.JIProfilerTest:search
     1    732,4    2,2  jiprof.JIProfilerTest:init
     1    293,8    0,9  jiprof.JIProfilerTest:main
     1      0,2    0,0  jiprof.JIProfilerTest:&lt;init&gt;

+--------------------------------------+
| Most expensive methods summarized    |
+--------------------------------------+

               Net
          ------------
 Count     Time    Pct  Location
 =====     ====    ===  ========
 10000  31896,8   96,9  jiprof.JIProfilerTest:search
     1    732,4    2,2  jiprof.JIProfilerTest:init
     1    293,8    0,9  jiprof.JIProfilerTest:main
     1      0,2    0,0  jiprof.JIProfilerTest:&lt;init&gt;</pre>
<p>An dem Ergebnis kann man sehen, dass allein die search Methode 96,9% der Rechenzeit verbraucht hat.</p>
<p>Jetzt lassen wir dieses Programm nochmal mit einer etwas intelligenteren Suchmethode ausführen und schauen uns das Ergebnis danach an.</p>
<pre class="prettyprint lang-java">public class JIProfilerTest {

    private static int maxRandom = 10000000;

    private int count = 1000000;

    private int[] nums;

    public static void main(String[] args) {
        Random random = new Random(System.currentTimeMillis());

        JIProfilerTest test = new JIProfilerTest();
        test.init(random);

        int numsFound = 0;

        for (int i = 0; i &lt; 10000; i++) {
            int number = random.nextInt(maxRandom) + 1;

            if (test.search(number) &gt; -1) {
                numsFound++;
            }
        }

        System.out.println(numsFound + " Nummern gefunden.");
    }

    private void init(Random random) {
        nums = new int[count];

        for (int i = 0; i &lt; count; i++) {
            nums[i] = random.nextInt(maxRandom);
        }

        Arrays.sort(nums);
    }

    private int search(int number) {
        int left, right, midpt;

        left = 0;
        right = nums.length - 1;

        while (left &lt;= right) {
            midpt = (int) ((left + right) / 2);

            if (number == nums[midpt]) {
                return midpt;
            } else if (number &gt; nums[midpt]) {
                left = midpt + 1;
            } else {
                right = midpt - 1;
            }
        }

        return -1;
    }

}</pre>
<p>Das Ergebnis:</p>
<pre>+----------------------------------------------------------------------
|  File: profile.txt
|  Date: 2009.03.04 20:49:54 PM
+----------------------------------------------------------------------

+------------------------------
| Thread depth limit: Unlimited
+------------------------------
+------------------------------
| Thread: 1
+------------------------------
              Time            Percent   
       ----------------- ---------------
 Count    Total      Net   Total     Net  Location
 =====    =====      ===   =====     ===  =========
     1    551,2    127,7   100,0    23,2  +--JIProfilerTest:main    (jiprof)
     1      0,1      0,1     0,0          | +--JIProfilerTest:&lt;init&gt;    (jiprof)
     1    319,6    319,6    58,0    58,0  | +--JIProfilerTest:init    (jiprof)
 10000    103,8    103,8    18,8    18,8  | +--JIProfilerTest:search    (jiprof)

+--------------------------------------
| Most expensive methods (by net time)
| Frame Count Limit: Unlimited
+--------------------------------------

               Net
          ------------
 Count     Time    Pct  Location
 =====     ====    ===  ========
     1    319,6   58,0  jiprof.JIProfilerTest:init
     1    127,7   23,2  jiprof.JIProfilerTest:main
 10000    103,8   18,8  jiprof.JIProfilerTest:search
     1      0,1    0,0  jiprof.JIProfilerTest:&lt;init&gt;

+--------------------------------------+
| Most expensive methods summarized    |
+--------------------------------------+

               Net
          ------------
 Count     Time    Pct  Location
 =====     ====    ===  ========
     1    319,6   58,0  jiprof.JIProfilerTest:init
     1    127,7   23,2  jiprof.JIProfilerTest:main
 10000    103,8   18,8  jiprof.JIProfilerTest:search
     1      0,1    0,0  jiprof.JIProfilerTest:&lt;init&gt;</pre>
<p>Dieser zweite Versuch hat schon eine insgesamt viel kürzere Laufzeit, außerdem benötigt die search Methode jetzt nur noch 18,8%.</p>
<p>Bei diesem Beispiel konnte man sicherlich auch ohne Profiler sagen, dass die zweite Variante schneller ist. Es gibt aber sicherlich andere Probleme, die nicht so einfach zu überblicken sind. Speziell wenn man versucht einen Flaschenhals in einem Programm zu finden kann ein Profiler gute Dienste leisten.</p>
<p>Interessant ist The Java Interactive Profiler sicherlich auch deswegen, da man ihn remote einsetzen kann und somit auch nützlich für Anwendungen sein kann, die in einem Servlet Container laufen. Das Einschalten des Profilers kann auch remote erfolgen, so dass auch nur spezielle Aspekte einer Anwendung getestet werden können.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.hachmeister.org/2009/03/java-profiling/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Makefile</title>
		<link>http://blog.hachmeister.org/2009/03/makefile/</link>
		<comments>http://blog.hachmeister.org/2009/03/makefile/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 19:04:31 +0000</pubDate>
		<dc:creator>Karsten</dc:creator>
		
		<category><![CDATA[Tools]]></category>

		<category><![CDATA[bash]]></category>

		<category><![CDATA[c++]]></category>

		<category><![CDATA[makefile]]></category>

		<guid isPermaLink="false">http://blog.hachmeister.org/?p=33</guid>
		<description><![CDATA[Für kleinere Projekte oder ad hoc Aufgaben in C++ ist es nützlich ein universelles Makefile bei der Hand zu haben. Daher hab ich etwas im Internet recherchiert und aus den folgenden beiden Quellen ein Makefile für meine Zwecke gebaut. 

Makefile aus dem GPWiki
Automating Program Compilation - Writing Makefiles

### Start of user configuration ###########################################

# Name your [...]]]></description>
			<content:encoded><![CDATA[<p>Für kleinere Projekte oder ad hoc Aufgaben in C++ ist es nützlich ein universelles Makefile bei der Hand zu haben. Daher hab ich etwas im Internet recherchiert und aus den folgenden beiden Quellen ein Makefile für meine Zwecke gebaut. <span id="more-33"></span></p>
<ul>
<li><a href="http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html">Makefile aus dem GPWiki</a></li>
<li><a href="http://users.actcom.co.il/~choo/lupg/tutorials/writing-makefiles/writing-makefiles.html">Automating Program Compilation - Writing Makefiles</a></li>
</ul>
<pre>### Start of user configuration ###########################################

# Name your executable.
TARGET = application

# Additional paths for PKG_CONFIG_PATH.
PKG_CONFIG_PATH =

# Additional libs, flags will be created with pkg-config.
LIBS =

# User flags.
CXXFLAGS =
LDFLAGS =

### End of user configuration #############################################

# Default build type.
TYPE = debug

# Special flags for each build type.
ifeq ($(TYPE),debug)
CXXFLAGS := $(value CXXFLAGS) -O0 -g3
LDFLAGS := $(value LDFLAGS)
endif

ifeq ($(TYPE),profile)
CXXFLAGS := $(value CXXFLAGS) -pg
LDFLAGS := $(value LDFLAGS) -pg
endif

ifeq ($(TYPE),release)
CXXFLAGS := $(value CXXFLAGS) -O3
LDFLAGS := $(value LDFLAGS) -s
endif

# The source, include and object store directory.
SRCDIR = src
INCDIR = include
OBJDIR = .$(TYPE)

# Compiler and compiler options.
CXX = g++
CXXFLAGS := $(value CXXFLAGS) -Wall -I$(INCDIR) -I$(SRCDIR) $(if $(LIBS),\
	$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --cflags $(LIBS)))

# Linker and linker options.
LD = g++
LDFLAGS := $(value LDFLAGS) $(if $(LIBS),\
	$(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs $(LIBS)))

# List of source files.
SRCS := $(foreach FILE,$(shell find $(SRCDIR) -name *.cpp | xargs), \
	$(subst $(SRCDIR)/, , $(FILE)))
# List of object files.
OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.o))
# List of dependency files.
DEPS := $(addprefix $(OBJDIR)/,$(SRCS:.cpp=.d))

.PHONY: init clean

$(TARGET): init $(OBJS)
	$(LD) $(LDFLAGS) -fPIC $(OBJS) -o $(TARGET)

$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
	$(CXX) -Wp,-MMD,$(OBJDIR)/$*.dd $(CXXFLAGS) -fPIC -c $&lt; -o $@
	@sed -e '1s/^\(.*\)$$/$(subst /,\/,$(dir $@))\1/' $(OBJDIR)/$*.dd &gt; \
		$(OBJDIR)/$*.d
	@rm -f $(OBJDIR)/$*.dd

init:
	@if [ ! -e $(OBJDIR) ]; then mkdir $(OBJDIR); fi;
	@$(foreach DIR,$(sort $(dir $(SRCS))), if [ ! -e $(OBJDIR)/$(DIR) ]; \
		then mkdir $(OBJDIR)/$(DIR); fi; )

clean:
	@rm -f $(TARGET) $(OBJS)

-include $(DEPS)</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.hachmeister.org/2009/03/makefile/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Code Beautifier</title>
		<link>http://blog.hachmeister.org/2009/03/code-beautifier/</link>
		<comments>http://blog.hachmeister.org/2009/03/code-beautifier/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 20:15:03 +0000</pubDate>
		<dc:creator>Karsten</dc:creator>
		
		<category><![CDATA[Tools]]></category>

		<category><![CDATA[bash]]></category>

		<category><![CDATA[c++]]></category>

		<category><![CDATA[command line]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[source code]]></category>

		<guid isPermaLink="false">http://blog.hachmeister.org/?p=5</guid>
		<description><![CDATA[Nach wie vor drucke ich immer noch gerne Dokumente/Sourcecode aus um sie auf Papier zu lesen, mir Anmerkungen reinzuschreiben oder einfach nicht vor dem Rechner sitzen zu müssen um den Text zu lesen.
Um Sourcecode zu drucken sollte dieser schön formatiert sein und möglichst auf 80 Zeichen begrenzt sein um ihn besser ausdrucken zu können. Für [...]]]></description>
			<content:encoded><![CDATA[<p>Nach wie vor drucke ich immer noch gerne Dokumente/Sourcecode aus um sie auf Papier zu lesen, mir Anmerkungen reinzuschreiben oder einfach nicht vor dem Rechner sitzen zu müssen um den Text zu lesen.</p>
<p>Um Sourcecode zu drucken sollte dieser schön formatiert sein und möglichst auf 80 Zeichen begrenzt sein um ihn besser ausdrucken zu können. Für C/C++ Code liefert die Kombination von indent und a2ps gute Ergebnisse. <span id="more-5"></span></p>
<h3>indent</h3>
<p>Zum Anfang muss erst einmal der Sourcecode formatiert werden, dafür kann man folgendes Kommando benutzen:</p>
<pre>indent in.cpp -st -bad -bap -bli0 -i4 -l79 -lc79 -ncs -npcs -nut -npsl \
-fca -fc1 &gt; out.cpp</pre>
<p>Hier einige Details zu den Optionen:</p>
<ul>
<li>-std: Der formatierte Sourcecode wird auf die Standardausgabe geschrieben.</li>
<li>-bad: Nach jedem Deklarationsblock wird eine Leerzeile eingefügt.</li>
<li>-bap: Nach jeder Funktions/Methodenblock wird eine Leerzeile eingefügt.</li>
<li>-bli0: Klammern werden nicht eingerückt.</li>
<li>-i4: Einrückung um 4 Leerzeichen.</li>
<li>-l79: Max. Länge einer Zeile auf 79 Zeichen festlegen.</li>
<li>-lc79: Max. Länge einer Kommentarzeile auf 79 Zeichen festlegen.</li>
<li>-ncs: Kein Leerzeichen nach einem Cast.</li>
<li>-npcs: Kein Leerzeichen hinter dem Funktionsnamen bei einem Funktionsaufruf.</li>
<li>-nut: Keine Tabulatoren verwenden, nur Leerzeichen.</li>
<li>-npsl: Rückgabewert einer Funktion in der gleichen Zeile wie den Funktionsnamen belassen.</li>
<li>-fca: Alle Kommentare formatieren.</li>
<li>-fc1: Kommentare formatieren, die in der ersten Spalte beginnen.</li>
</ul>
<p>Detailiertere Angaben zu den einzelnen Optionen, inkl. Beispielen, findet man in der Manpage von indent:</p>
<pre>man indent</pre>
<p>Das Kommando um C/C++ Sourcecode zu formatieren ist fertig, leider kann ich mir eine solche Anzahl von Optionen über einen längeren Zeitraum nicht merken. Dafür bietet das indent Kommando eine profile Datei, die man sich in seinem Home-Verzeichnis anlegen kann.</p>
<p>indent liest die Datei .indent.pro ein, wenn vorhanden. Die einzelnen Optionen können in dieser Datei gespeichert werden, genauso wie man sie für das Kommando angeben würde, als eine Zeile in der Datei.</p>
<h3>a2ps</h3>
<p>Jetzt geht es ans Drucken. mit folgendem Kommando kann man den gerade formatierten Sourcecode jetzt drucken:</p>
<pre>a2ps out.cpp</pre>
<p>Hat man keinen Standarddrucker eingestellt oder will man es auf einen anderen Drucker ausgeben kann man den Druckernamen mitgeben:</p>
<pre>a2ps -P &lt;druckername&gt; out.cpp</pre>
<p>Standardmäßig werden 2 Seiten auf eine DIN-A 4 Seite gedruckt, wer lieber nur eine Seite im Hochformat gedruckt haben will gibt folgendes an:</p>
<pre>a2ps -1 out.cpp</pre>
<h4>Noch 2 kleine Hinweise</h4>
<p>Da a2ps keine UTF-8 Kodierung verarbeiten kann, ist es hilfreich die Dateien, sofern sie in der UTF-8 Kodierung vorliegen, zuvor umzuwandeln:</p>
<pre>recode utf8..latin1 out.cpp</pre>
<p>Möchte man sein Ergebnis zuerst am Bildschirm betrachten sollte man als Drucker display angeben, so wird die Postscript Ausgabe nur am Bildschirm geöffnet.</p>
<pre>a2ps -P display out.cpp</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.hachmeister.org/2009/03/code-beautifier/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
