<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2germanfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" version="2.0">

<channel>
	<title>The Software Developer</title>
	
	<link>http://blog.hachmeister.org</link>
	<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>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/thesoftwaredeveloper" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="thesoftwaredeveloper" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://add.my.yahoo.com/content?lg=de&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://us.i1.yimg.com/us.yimg.com/i/de/my/addtomyyahoo4.gif">Subscribe with Mein Yahoo!</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bloglines.com/sub/http://feeds.feedburner.com/thesoftwaredeveloper" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.newsalloy.com/?rss=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.yourminis.com/subscribe.aspx?u=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.yourminis.com/images/addtoyourminisbadge.gif">Subscribe with Yourminis.com</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://hub.netomat.net/account/account.autoSubscribe.jspa?urls=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.netomat.net/blogger/images/icon_netomat_feedbutton.gif">Subscribe with netomat Hub</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.wikio.com/subscribe?url=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Ffeeds.feedburner.com%2Fthesoftwaredeveloper" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Ein einfacher C++ Tokenizer</title>
		<link>http://blog.hachmeister.org/2009/03/ein-einfacher-cpp-tokenizer/</link>
		<comments>http://blog.hachmeister.org/2009/03/ein-einfacher-cpp-tokenizer/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 12:56:16 +0000</pubDate>
		<dc:creator>Karsten</dc:creator>
		
		<category><![CDATA[Code]]></category>

		<category><![CDATA[c++]]></category>

		<category><![CDATA[tokenizer]]></category>

		<guid isPermaLink="false">http://blog.hachmeister.org/?p=82</guid>
		<description><![CDATA[Sehr viele Daten müssen erstmal aus einer Datei eingelesen werden. Dabei kann ein Tokenizer gute Dienste leisten um strukturierte Daten in die entsprechenden Stücke zu unterteilen. 
#ifndef TOKENIZER_H_
#define TOKENIZER_H_

#include &#60;string&#62;

using namespace std;

enum DelimType
{
  WHITESPACE = 0, ORDINARY = 1
};

class Tokenizer
{
public:
  Tokenizer(const string text);
  virtual ~Tokenizer();

  bool has_next();
  string next();

  void add_delims(int begin, int end, DelimType [...]]]></description>
			<content:encoded><![CDATA[<p>Sehr viele Daten müssen erstmal aus einer Datei eingelesen werden. Dabei kann ein Tokenizer gute Dienste leisten um strukturierte Daten in die entsprechenden Stücke zu unterteilen. <span id="more-82"></span></p>
<pre class="prettyprint lang-cpp">#ifndef TOKENIZER_H_
#define TOKENIZER_H_

#include &lt;string&gt;

using namespace std;

enum DelimType
{
  WHITESPACE = 0, ORDINARY = 1
};

class Tokenizer
{
public:
  Tokenizer(const string text);
  virtual ~Tokenizer();

  bool has_next();
  string next();

  void add_delims(int begin, int end, DelimType type);

private:
  void find_token();

private:
  unsigned int _pos;
  string _text;
  string _token;
  bool _token_available;
  DelimType _delims[256];
};

#endif</pre>
<pre class="prettyprint lang-cpp">#include &lt;iostream&gt;

#include "Tokenizer.h"

Tokenizer::Tokenizer(const string text) :
  _pos(0), _text(text), _token_available(false)
{
  _token.clear();
  add_delims(0x0, 0xFF, WHITESPACE);
  add_delims(0x30, 0x39, ORDINARY);
  add_delims(0x41, 0x5A, ORDINARY);
  add_delims(0x61, 0x7A, ORDINARY);
}

Tokenizer::~Tokenizer()
{
}

bool Tokenizer::has_next()
{
  find_token();

  if (_token_available)
  {
    return true;
  }

  return false;
}

string Tokenizer::next()
{
  find_token();

  if (_token_available)
  {
    _token_available = false;
    return _token;
  }

  throw "No next token!";
}

void Tokenizer::add_delims(int begin, int end, DelimType type)
{
  if (begin &lt; 0)
  {
    begin = 0;
  }

  if (end &gt; 255)
  {
    end = 255;
  }

  for (int i = begin; i &lt;= end; ++i)
  {
    _delims[i] = type;
  }
}

void Tokenizer::find_token()
{
  if (_pos &gt;= _text.length() || _token_available)
  {
    return;
  }

  _token.clear();
  _token_available = false;

  while (_pos &lt; _text.length())
  {
    char chr = _text.at(_pos);
    DelimType type = _delims[(int) chr];
    _pos++;

    if (type == ORDINARY)
    {
      _token.append(1, chr);
      _token_available = true;
    }
    else if (_token_available &amp;&amp; type == WHITESPACE)
    {
      break;
    }
  }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.hachmeister.org/2009/03/ein-einfacher-cpp-tokenizer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Faceted Search mit Lucene</title>
		<link>http://blog.hachmeister.org/2009/03/faceted-search-mit-lucene/</link>
		<comments>http://blog.hachmeister.org/2009/03/faceted-search-mit-lucene/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 22:14:02 +0000</pubDate>
		<dc:creator>Karsten</dc:creator>
		
		<category><![CDATA[Technologien]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[lucene]]></category>

		<category><![CDATA[search]]></category>

		<guid isPermaLink="false">http://blog.hachmeister.org/?p=73</guid>
		<description><![CDATA[Lucene ist eine leistungsfähige Volltext-Suchmaschine geschrieben in Java. Faceted Search ist ein immer öfter gefordertes Feature bei dem Einsatz einer Suchmaschine.
In diesem Artikel möchte ich zeigen, wie man eine einfache Faceted Search mit Lucene umsetzen kann. 
Zum Einsammeln der Facetten benötigen wir eine Implementierung der HitCollector Klasse. Hier wird die TopFieldDocCollector Klasse erweitert, wird keine [...]]]></description>
			<content:encoded><![CDATA[<p>Lucene ist eine leistungsfähige Volltext-Suchmaschine geschrieben in Java. Faceted Search ist ein immer öfter gefordertes Feature bei dem Einsatz einer Suchmaschine.</p>
<p>In diesem Artikel möchte ich zeigen, wie man eine einfache Faceted Search mit Lucene umsetzen kann. <span id="more-73"></span></p>
<p>Zum Einsammeln der Facetten benötigen wir eine Implementierung der HitCollector Klasse. Hier wird die TopFieldDocCollector Klasse erweitert, wird keine weitere Sortierung außer nach Relevanz benötigt, so kann man auch die Klasse TopDocCollector nutzen.</p>
<p>Zu beachten ist, dass diese Implementierung einer Faceted Search nur funktioniert, wenn Felder die zur Facettenbildung benutzt werden, nur einen einzelnen Wert pro Dokument haben. Andernfalls ist das Verhalten undefiniert, da die Werte für die Facetten über die Klasse FieldCache erzeugt werden. Um mehrere Werte für Facettenfelder zu erlauben ist eine eigene Implementierung einer FieldCache Klasse notwendig, die mehrere Werte pro Feld enthalten kann.</p>
<p>Hier nun die Implementierung:</p>
<pre class="prettyprint lang-java">public class FacetedCollector extends TopFieldDocCollector {

  private Map&lt;String, String[]&gt; fieldCaches;

  private Map&lt;String, Map&lt;String, Integer&gt;&gt; facetsMap;

  public FacetedCollector(String[] fields, IndexReader reader, Sort sort,
      int numHits) throws IOException {
    super(reader, sort, numHits);

    this.facetsMap = new HashMap&lt;String, Map&lt;String, Integer&gt;&gt;();
    this.fieldCaches = new HashMap&lt;String, String[]&gt;();

    for (String field : fields) {
      facetsMap.put(field, new HashMap&lt;String, Integer&gt;());
      fieldCaches.put(field, FieldCache.DEFAULT.getStrings(reader, field));
    }
  }

  @Override
  public void collect(int doc, float score) {
    super.collect(doc, score);

    for (Entry&lt;String, Map&lt;String, Integer&gt;&gt; e : facetsMap.entrySet()) {
      Map&lt;String, Integer&gt; values = e.getValue();
      String value = fieldCaches.get(e.getKey())[doc];

      if (value != null) {
        Integer count = values.get(value);

        if (count == null) {
          values.put(value, 1);
        } else {
          values.put(value, count + 1);
        }
      }
    }
  }

  public Map&lt;String, Map&lt;String, Integer&gt;&gt; getFacetsMap() {
    return facetsMap;
  }

}</pre>
<p>Zusätzlich zu den Parametern des Konstrukturs der Klasse TopFieldDocCollector werden die Feldnamen im Stringarray fields übergeben.</p>
<p>Über die fieldCaches kann direkt auf den Wert eines Feldes eines bestimmten Dokumentes zugegriffen werden, ohne im Index suchen zu müssen. Die Arrays für die Werte der verschiedenen Felder befinden sich direkt im Ram und werden von der FieldCache Klasse bei dem ersten Zugriff erzeugt. Damit dauert die erste Suche über den FacetedCollector, je nach Anzahl der Dokumente im Index, einige Zeit.</p>
<p>Um den Speicherbedarf möglichst niedrig zu halten sollte versucht werden die Werte über byte, short oder int Felder im Index abzulegen.</p>
<p>Hier eine beispielhafte Benutzung der FacetedCollector Klasse:</p>
<pre class="prettyprint lang-java">public class FacetedSearch {

  public static void main(String[] args) {
    String path = args[0];
    String queryStr = args[1];

    try {
      QueryParser parser =
          new QueryParser("title", new StandardAnalyzer());
      Query query = parser.parse(queryStr);

      IndexSearcher searcher = new IndexSearcher(path);
      String[] fields = { "language", "year" };
      IndexReader reader = searcher.getIndexReader();
      FacetedCollector collector =
          new FacetedCollector(fields, reader, Sort.RELEVANCE, 10);
      searcher.search(query, collector);

      Map&lt;String, Map&lt;String, Integer&gt;&gt; facetsMap =
          collector.getFacetsMap();

      for (Entry&lt;String, Map&lt;String, Integer&gt;&gt; fieldEntry : facetsMap
          .entrySet()) {
        System.out.println(" - " + fieldEntry.getKey());

        for (Entry&lt;String, Integer&gt; valueEntry : fieldEntry.getValue()
            .entrySet()) {
          System.out.println("   - " + valueEntry.getKey() + " ("
              + valueEntry.getValue() + ")");
        }
      }

      searcher.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.hachmeister.org/2009/03/faceted-search-mit-lucene/feed/</wfw:commentRss>
		</item>
		<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>
