[gegl] Added performance tracking framework



commit a643a0f3813926da2cf63bac6c8a556eda73aa47
Author: �yvind Kolås <pippin gimp org>
Date:   Sun Feb 7 14:01:01 2010 +0000

    Added performance tracking framework

 perf/Makefile                        |   51 +++++++++
 perf/README                          |    9 ++
 perf/create-report.rb                |  186 ++++++++++++++++++++++++++++++++++
 perf/tests/Makefile                  |   14 +++
 perf/tests/bblur.c                   |   26 +++++
 perf/tests/bcontrast-minichunk.c     |   34 ++++++
 perf/tests/bcontrast.c               |   31 ++++++
 perf/tests/blur.c                    |   28 +++++
 perf/tests/cc.cc                     |   59 +++++++++++
 perf/tests/comp.c                    |   33 ++++++
 perf/tests/gegl-c.h                  |  157 ++++++++++++++++++++++++++++
 perf/tests/passthrough.c             |   32 ++++++
 perf/tests/rotate.c                  |   26 +++++
 perf/tests/test-common.h             |   37 +++++++
 perf/tests/test-gegl-buffer-access.c |   38 +++++++
 15 files changed, 761 insertions(+), 0 deletions(-)
---
diff --git a/perf/Makefile b/perf/Makefile
new file mode 100644
index 0000000..c77f053
--- /dev/null
+++ b/perf/Makefile
@@ -0,0 +1,51 @@
+PROJECT_PATH = ../
+
+# number of revisions to create
+START_REV    = master
+REVISIONS    = 20
+
+#comment the following line out to see what the makefile is doing
+.SILENT:
+
+REFS    = $(wildcard jobs/*)
+REPORTS = $(subst jobs/,reports/,$(REFS))
+
+# use random mode for a bit first to get better ranges for plots and less noise
+all: sequential reset 
+#all: $(REPORTS) reset
+
+
+sequential: 
+	for a in `cat joblist`;do echo $$a;make reports/$$a;done
+
+reset:
+	test -d jobs || ( make jobs ; make )
+	rm -rf build
+	#echo "Have 0 jobs, edit Makefile to inspect run options, then type make jobs"  && false )
+reports/%: 
+	if [ ! -d build ]; then git clone -s $(PROJECT_PATH) build ; fi
+	( cd build; git checkout `echo $@|sed s:reports/::` )
+	git log -1 > $@ || true
+	(cd build; if [ ! -f Makefile ]; then ./autogen.sh ; fi ; \
+	 CC="ccache gcc" make -j3 && sudo make -j3 install ) > $  log 2>&1 && \
+	 ( echo -n 'built and installed, testing...' ; \
+	   make -C tests clean ; make -C tests ; \
+	   make -C tests check >> $@ )\
+	 || true
+	echo
+	./create-report.rb
+	echo
+jobs: 
+	if [ ! -d build ]; then git clone -s $(PROJECT_PATH) build ; fi
+	( cd build; git checkout $(START_REV) )
+	mkdir reports > /dev/null 2>&1 || true 
+	mkdir jobs > /dev/null 2>&1 || true
+	rm -f jobs/*
+	( cd build; git log |grep -r "^commit " | head -n $(REVISIONS) | tac | sed "s/commit //" > ../joblist )
+	for a in `cat joblist`;do touch jobs/$$a;done 
+	echo Made `ls -1 jobs|wc -w` jobs
+
+clean:
+	rm -rf reports
+	rm -rf jobs
+	rm -f joblist
diff --git a/perf/README b/perf/README
new file mode 100644
index 0000000..f1c15b4
--- /dev/null
+++ b/perf/README
@@ -0,0 +1,9 @@
+Performance tracking framework
+------------------------------
+
+This directory contains a simple framework to track performance development of
+a set of GEGL tests over time. It requires ruby and ruby cairo bindings to
+work.
+
+Hopefully just typing make would trigger generation of a graph for the last
+20 commits, edit the Makefile to change this behavior.
diff --git a/perf/create-report.rb b/perf/create-report.rb
new file mode 100755
index 0000000..a6298ec
--- /dev/null
+++ b/perf/create-report.rb
@@ -0,0 +1,186 @@
+#!/usr/bin/env ruby
+#
+require 'cairo'
+
+def cairo_surface(w,h)
+    surface = Cairo::PDFSurface.new("report.pdf", w,h)
+    cr = Cairo::Context.new(surface)
+    yield(cr)
+end 
+
+class Database
+
+    def initialize()
+        @vals = Hash.new
+        @runs = Array.new
+        @colors = [
+          [0,0,1, 0.8],
+          [0,1,0, 0.8],
+          [0,1,1, 0.8],
+          [1,0,0, 0.8],
+          [1,0,1, 0.8],
+          [1,1,0, 0.8],
+          #[0.5,0.5,0.5,0.8],
+          # gray has too little contrast against the background
+          [0.5,0.5,1, 0.8],
+          [0.5,1,0.5, 0.8],
+          [0.5,1,1, 0.8],
+          [1,0.5,0.5, 0.8],
+          [1,0.5,1, 0.8],
+          [1,1,0.5, 0.8],
+          [1,1,1, 0.8],
+        ]
+        @width  = 1024
+        @height = 300
+
+        @marginlx = 10
+        @marginrx = 140
+        @marginy = 10
+    end
+    def val_max(key)
+       max=0
+       @runs.each { |run|
+         val = @vals[key][run]
+         if val and val > max
+           max = val
+         end
+       }
+       max
+    end
+    def val_min(key)
+       min=9999990
+       @runs.each { |run|
+         val = @vals[key][run]
+         if val and val < min
+           min = val
+         end
+       }
+       min
+    end
+    def add_run(run)
+        @runs = @runs + [run]
+    end
+    def add_entry(run, name, val)
+        if ! vals[name]
+            @vals[name]=Hash.new
+        end
+        # check if there is an existing value,
+        # and perhaps have different behaviors
+        # associated with 
+        @vals[name][run] = val.to_f
+    end
+
+    def drawbg cr
+
+            cr.set_source_rgba(0.2, 0.2, 0.2, 1)
+            cr.paint 
+
+            i=0
+              @runs.each { |run|
+
+                    if i % 2 == 1
+                    cr.move_to 1.0 * i / @runs.length * (@width - @marginlx- marginrx) + @marginlx,
+                               0 * (@height - @marginy*2) + @marginy
+                    cr.line_to 1.0 * i / @runs.length * (@width - @marginlx- marginrx) + @marginlx,
+                               1.0 * (@height - @marginy*2) + @marginy
+                    cr.rel_line_to(1.0 / @runs.length * (@width - @marginlx- marginrx), 0)
+                    cr.rel_line_to(0, -(@height - @marginy*2))
+
+                    cr.set_source_rgba([0.25,0.25,0.25,1])
+                    cr.fill
+                    end
+                    
+                    i+=1
+              }
+          end
+
+    def drawtext cr
+
+              i = 0
+              @runs.each { |run|
+                    y = i * 10 + 20
+                    while y > @height - @marginy
+                        y = y - @height + @marginy + 10
+                    end
+                    cr.move_to 1.0 * i / @runs.length * (@width - @marginlx- marginrx) + @marginlx, y
+
+                    cr.set_source_rgba(0.6,0.6,0.6,1)
+                    cr.show_text(run[0..7])
+                    i+=1
+              }
+    end
+
+    def draw_limits cr, key
+        cr.move_to @width - @marginrx, 20
+        cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
+        cr.show_text(" #{val_max(key)} mb/s")
+        cr.move_to @width - @marginrx, @height - @marginy
+        cr.show_text(" #{val_min(key)} mb/s")
+    end
+
+    def draw_val cr, key, valno
+              min = val_min(key)
+              max = val_max(key)
+
+              cr.set_source_rgba(@colors[valno])
+              cr.move_to(@width - 137, valno * 14 + @marginy + 20)
+              cr.show_text(key)
+
+              cr.line_width = 2
+              cr.new_path
+
+              i = 0
+              @runs.each { |run|
+                val = @vals[key][run]
+                if val 
+                    cr.line_to 1.0 * (i+0.5) / @runs.length * (@width - @marginlx- marginrx) + @marginlx,
+                               (1.0 - ((val-min) * 1.0 / (max - min))) * (@height - @marginy*2) + @marginy
+                end
+                i = i + 1
+              }
+              cr.stroke
+    end
+
+    def create_report 
+
+
+        cairo_surface(@width, @height) { |cr|
+
+            drawbg cr
+            valno = 0
+            @vals.each { |key, value|
+               draw_val cr, key, valno
+               valno += 1
+            }
+            drawtext cr
+            cr.target.write_to_png("report.png")
+
+            valno = 0 
+            @vals.each { |key, value|
+               cr.show_page
+               drawbg cr
+               draw_val cr, key, valno
+               drawtext cr
+               draw_limits cr, key
+               valno += 1
+            }
+        }
+    end
+end
+
+generator = Database.new
+
+items = File.open('joblist').each { |rev|
+  rev.strip!
+  generator.add_run(rev)
+  filename = "reports/" + rev;
+  if File.exist?(filename)
+      File.open(filename).each { |line| 
+         if line =~ /^@ (.*):(.*)/
+            generator.add_entry(rev, $1, $2)
+         end
+      }
+  end
+}
+
+generator.create_report
diff --git a/perf/tests/Makefile b/perf/tests/Makefile
new file mode 100644
index 0000000..01555d0
--- /dev/null
+++ b/perf/tests/Makefile
@@ -0,0 +1,14 @@
+CFILES = $(wildcard *.c)
+bins   = $(subst ,,$(CFILES:.c=))
+
+all: $(bins)
+
+%: %.c $(GEGLHEADERS)
+	$(CC) `pkg-config gegl --cflags --libs` -Wall -O2  -o $@ $<
+
+check: $(bins)
+	for a in $(bins); do ./$$a;done
+
+clean:
+	rm -f $(bins)
+
diff --git a/perf/tests/bblur.c b/perf/tests/bblur.c
new file mode 100644
index 0000000..4d3bff2
--- /dev/null
+++ b/perf/tests/bblur.c
@@ -0,0 +1,26 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                            gegl_node ("gegl:box-blur", "radius", 2.0, NULL,
+                            gegl_node ("gegl:buffer-source", "buffer", buffer, NULL))));
+
+  test_start ();
+  gegl_node_process (sink);
+  test_end ("box-blur", gegl_buffer_get_pixel_count (buffer) * 16);
+  g_object_unref (gegl);
+  g_object_unref (buffer);
+
+  return 0;
+}
diff --git a/perf/tests/bcontrast-minichunk.c b/perf/tests/bcontrast-minichunk.c
new file mode 100644
index 0000000..19afd13
--- /dev/null
+++ b/perf/tests/bcontrast-minichunk.c
@@ -0,0 +1,34 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+  gint i;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  g_object_set (gegl_config (), "chunk-size", 128 * 128, NULL);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+#define ITERATIONS 1
+  test_start ();
+  for (i=0;i< ITERATIONS;i++)
+    {
+      gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                                gegl_node ("gegl:brightness-contrast", "contrast", 0.2, NULL,
+                                gegl_node ("gegl:buffer-source", "buffer", buffer, NULL))));
+
+      gegl_node_process (sink);
+      g_object_unref (gegl);
+      g_object_unref (buffer2);
+    }
+  test_end ("bcontrast-minichunk", gegl_buffer_get_pixel_count (buffer) * 16 * ITERATIONS);
+
+
+  return 0;
+}
diff --git a/perf/tests/bcontrast.c b/perf/tests/bcontrast.c
new file mode 100644
index 0000000..070b186
--- /dev/null
+++ b/perf/tests/bcontrast.c
@@ -0,0 +1,31 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+  gint i;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+#define ITERATIONS 3
+  test_start ();
+  for (i=0;i< ITERATIONS;i++)
+    {
+      gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                                gegl_node ("gegl:brightness-contrast", "contrast", 0.2, NULL,
+                                gegl_node ("gegl:buffer-source", "buffer", buffer, NULL))));
+
+      gegl_node_process (sink);
+      g_object_unref (gegl);
+      g_object_unref (buffer2);
+    }
+  test_end ("bcontrast", gegl_buffer_get_pixel_count (buffer) * 16 * ITERATIONS);
+
+  return 0;
+}
diff --git a/perf/tests/blur.c b/perf/tests/blur.c
new file mode 100644
index 0000000..dcfbab3
--- /dev/null
+++ b/perf/tests/blur.c
@@ -0,0 +1,28 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                            gegl_node ("gegl:gaussian-blur",
+                                       "std-dev-x", 0.5,
+                                       "std-dev-y", 0.5,
+                                       NULL,
+                            gegl_node ("gegl:buffer-source", "buffer", buffer, NULL))));
+
+  test_start ();
+  gegl_node_process (sink);
+  test_end ("gaussian-blur", gegl_buffer_get_pixel_count (buffer) * 16);
+  g_object_unref (gegl);
+
+  return 0;
+}
diff --git a/perf/tests/cc.cc b/perf/tests/cc.cc
new file mode 100644
index 0000000..e6e97d7
--- /dev/null
+++ b/perf/tests/cc.cc
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <glib.h>
+#include <gegl.h>
+#include "misc.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglBuffer *bufferB;
+  GeglNode   *gegl, *sink;
+  long ticks;
+  gint i;
+  gchar *infile;
+  gchar *infileB;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  infile = "/home/pippin/images/movie_narrative_charts_large.png";
+  infileB = "/home/pippin/images/movieb.png";
+
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &bufferB, NULL,
+                            gegl_node ("fooit", NULL,
+                            gegl_node ("gegl:png-load", "path",  infileB, NULL))));
+
+  gegl_node_process (sink);
+  g_object_unref (gegl);
+
+  g_print (":::%s\n", babl_get_name (gegl_buffer_get_format (bufferB)));
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer, NULL,
+                            gegl_node ("fooit", NULL,
+                            gegl_node ("gegl:png-load", "path",  infile, NULL))));
+
+  gegl_node_process (sink);
+  g_object_unref (gegl);
+
+  g_print (":::%s\n", babl_get_name (gegl_buffer_get_format (buffer)));
+
+#define ITERATIONS 3
+  ticks = gegl_ticks ();
+  for (i=0;i< ITERATIONS;i++)
+    {
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                            gegl_node ("gegl:over", NULL,
+                            gegl_node ("gegl:buffer-source", "buffer", buffer, NULL),
+                            gegl_node ("gegl:buffer-source", "buffer", bufferB, NULL))));
+
+    gegl_node_process (sink);
+  g_object_unref (gegl);
+  g_object_unref (buffer2);
+    }
+
+  ticks = gegl_ticks ()-ticks;
+  g_print ("@ over: %f Mpixels/sec\n", ((1.0 * gegl_buffer_get_width (buffer) * gegl_buffer_get_height (buffer) * ITERATIONS/1000000)/ ( (ticks) / 1000.0) * 1000.0));
+
+  return 0;
+}
diff --git a/perf/tests/comp.c b/perf/tests/comp.c
new file mode 100644
index 0000000..4402dfb
--- /dev/null
+++ b/perf/tests/comp.c
@@ -0,0 +1,33 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglBuffer *bufferB;
+  GeglNode   *gegl, *sink;
+  gint i;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  bufferB = test_buffer (2048, 2048, babl_format ("RGBA float"));
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+#define ITERATIONS 5
+  test_start ();
+  for (i=0;i< ITERATIONS;i++)
+    {
+      gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                                gegl_node ("gegl:over", NULL,
+                                gegl_node ("gegl:buffer-source", "buffer", buffer, NULL),
+                                gegl_node ("gegl:buffer-source", "buffer", bufferB, NULL))));
+
+      gegl_node_process (sink);
+      g_object_unref (gegl);
+      g_object_unref (buffer2);
+    }
+  test_end ("over", gegl_buffer_get_pixel_count (bufferB) * ITERATIONS * 16);
+  return 0;
+}
diff --git a/perf/tests/gegl-c.h b/perf/tests/gegl-c.h
new file mode 100644
index 0000000..0e76293
--- /dev/null
+++ b/perf/tests/gegl-c.h
@@ -0,0 +1,157 @@
+/* This file is part of GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2009 �yvind Kolås
+ */
+
+#include <gegl.h>
+#include <gegl-plugin.h>
+#include <glib/gprintf.h>
+#include <gobject/gvaluecollector.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+
+
+
+static void
+gegl_graph_adopt (GeglNode *graph, GeglNode *node)
+{
+  GeglNode *input, *aux;
+
+  gegl_node_add_child (graph, node);
+  g_object_unref (node);
+
+  if ((input = gegl_node_get_producer (node, "input", NULL)))
+    gegl_graph_adopt (graph, input);
+  if ((aux = gegl_node_get_producer (node, "aux", NULL)))
+    gegl_graph_adopt (graph, aux);
+}
+
+GeglNode *
+gegl_graph (GeglNode *node)
+{
+  GeglNode *graph;
+
+  graph = g_object_new (GEGL_TYPE_NODE, NULL);
+  if (gegl_node_get_pad (node, "output"))
+    {
+      GeglNode *outproxynop = gegl_node_get_output_proxy (graph, "output");
+      gegl_node_connect_to (node, "output", outproxynop, "input"); 
+    }
+  gegl_graph_adopt (graph, node);
+  return graph;
+}
+
+GeglNode *
+gegl_node (const gchar *type,
+           const gchar *firstname,
+           ...)
+{
+  GeglNode      *node;
+  GeglOperation *operation;
+  va_list        var_args;
+  const gchar   *property_name;
+
+  node = g_object_new (GEGL_TYPE_NODE, "operation", type, NULL);
+  g_object_get (G_OBJECT (node), "gegl-operation", &operation, NULL);
+
+  g_object_freeze_notify (G_OBJECT (node));
+  va_start (var_args, firstname);
+  property_name = firstname;
+  while (property_name)
+    {
+      GValue      value = { 0, };
+      GParamSpec *pspec = NULL;
+      gchar      *error = NULL;
+
+      if (!strcmp (property_name, "name"))
+        {
+          pspec = g_object_class_find_property (
+            G_OBJECT_GET_CLASS (G_OBJECT (node)), property_name);
+
+          g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+          G_VALUE_COLLECT (&value, var_args, 0, &error);
+          if (error)
+            {
+              g_warning ("%s: %s", G_STRFUNC, error);
+              g_free (error);
+              g_value_unset (&value);
+              break;
+            }
+          g_object_set_property (G_OBJECT (node), property_name, &value);
+          g_value_unset (&value);
+        }
+      else
+        {
+          if (operation)
+            {
+              pspec = g_object_class_find_property (
+                G_OBJECT_GET_CLASS (G_OBJECT (operation)), property_name);
+            }
+          if (!pspec)
+            {
+              g_warning ("%s:%s has no property named: '%s'",
+                         G_STRFUNC,
+                         G_OBJECT_TYPE_NAME (operation), property_name);
+              break;
+            }
+          if (!(pspec->flags & G_PARAM_WRITABLE))
+            {
+              g_warning ("%s: property (%s of operation class '%s' is not writable",
+                         G_STRFUNC,
+                         pspec->name,
+                         G_OBJECT_TYPE_NAME (operation));
+              break;
+            }
+
+          g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+          G_VALUE_COLLECT (&value, var_args, 0, &error);
+          if (error)
+            {
+              g_warning ("%s: %s", G_STRFUNC, error);
+              g_free (error);
+              g_value_unset (&value);
+              break;
+            }
+          g_object_set_property (G_OBJECT (operation), property_name, &value);
+          g_value_unset (&value);
+        }
+
+      property_name = va_arg (var_args, gchar *);
+    }
+  g_object_thaw_notify (G_OBJECT (node));
+
+  /* The input pads checked for are hard-coded, if no output is connected
+   * pass NULL to indicate no connected node.
+   */
+  if (gegl_node_get_pad (node, "input"))
+    {
+      GeglNode *input = va_arg (var_args, GeglNode*);
+
+      if (input)
+        gegl_node_connect_from (node, "input", input, "output");
+    }
+
+  if (gegl_node_get_pad (node, "aux"))
+    {
+      GeglNode *aux = va_arg (var_args, GeglNode*);
+
+      if (aux)
+        gegl_node_connect_from (node, "aux", aux, "output");
+    }
+  va_end (var_args);
+  return node;
+}
diff --git a/perf/tests/passthrough.c b/perf/tests/passthrough.c
new file mode 100644
index 0000000..eefeeaf
--- /dev/null
+++ b/perf/tests/passthrough.c
@@ -0,0 +1,32 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+  gint i;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+#define ITERATIONS 3
+  test_start ();
+  for (i=0;i< ITERATIONS;i++)
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                            gegl_node ("gegl:brightness-contrast", "contrast", 0.2, NULL,
+                            gegl_node ("gegl:brightness-contrast", "contrast", 0.2, NULL,
+                            gegl_node ("gegl:brightness-contrast", "contrast", 0.2, NULL,
+                            gegl_node ("gegl:brightness-contrast", "contrast", 1.2, NULL,
+                            gegl_node ("gegl:buffer-source", "buffer", buffer, NULL)))))));
+
+  gegl_node_process (sink);
+  test_end ("passthrough", gegl_buffer_get_pixel_count (buffer2) * 16);
+  g_object_unref (gegl);
+  g_object_unref (buffer2);
+
+  return 0;
+}
diff --git a/perf/tests/rotate.c b/perf/tests/rotate.c
new file mode 100644
index 0000000..28a1bbd
--- /dev/null
+++ b/perf/tests/rotate.c
@@ -0,0 +1,26 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer *buffer, *buffer2;
+  GeglNode   *gegl, *sink;
+
+  g_thread_init (NULL);
+  gegl_init (&argc, &argv);
+
+  buffer = test_buffer (2048, 2048, babl_format ("RGBA float"));
+
+  gegl = gegl_graph (sink = gegl_node ("gegl:buffer-sink", "buffer", &buffer2, NULL,
+                            gegl_node ("gegl:rotate", "degrees", 4.0, NULL,
+                            gegl_node ("gegl:buffer-source", "buffer", buffer, NULL))));
+
+  test_start ();
+  gegl_node_process (sink);
+  test_end ("rotate",  gegl_buffer_get_pixel_count (buffer) * 16);
+
+  g_object_unref (gegl);
+
+  return 0;
+}
diff --git a/perf/tests/test-common.h b/perf/tests/test-common.h
new file mode 100644
index 0000000..4a91265
--- /dev/null
+++ b/perf/tests/test-common.h
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include <glib.h>
+#include <gegl.h>
+
+static long ticks_start;
+
+glong gegl_ticks (void);
+
+void test_start (void)
+{
+  ticks_start = gegl_ticks ();
+}
+
+void test_end (const gchar *id,
+               glong        bytes)
+{
+  long ticks = gegl_ticks ()-ticks_start;
+  g_print ("@ %s: %.2f megabytes/second\n",
+       id, (bytes / 1024.0 / 1024.0)  / (ticks / 1000000.0));
+}
+
+GeglBuffer *test_buffer (gint width,
+                         gint height,
+                         Babl *format)
+{
+  GeglRectangle bound = {0, 0, width, height};
+  GeglBuffer *buffer;
+  gfloat *buf = g_malloc0 (width * height * 16);
+  gint i;
+  buffer = gegl_buffer_new (&bound, format);
+  for (i=0; i < width * height * 4; i++)
+    buf[i] = g_random_double_range (-0.5, 2.0);
+  gegl_buffer_set (buffer, NULL, babl_format ("RGBA float"), buf, 0);
+  g_free (buf);
+  return buffer;
+}
+
diff --git a/perf/tests/test-gegl-buffer-access.c b/perf/tests/test-gegl-buffer-access.c
new file mode 100644
index 0000000..debde06
--- /dev/null
+++ b/perf/tests/test-gegl-buffer-access.c
@@ -0,0 +1,38 @@
+#include "test-common.h"
+
+gint
+main (gint    argc,
+      gchar **argv)
+{
+  GeglBuffer    *buffer;
+  GeglRectangle  bound = {0, 0, 4096, 4096};
+  gchar *buf;
+  gint i;
+
+  g_thread_init (NULL);
+  gegl_init (NULL, NULL);
+  buffer = gegl_buffer_new (&bound, babl_format ("RGBA float"));
+  buf = g_malloc0 (bound.width * bound.height * 16);
+
+#define ITERATIONS 5
+
+  test_start ();
+  for (i=0;i<ITERATIONS;i++)
+    {
+      gegl_buffer_set (buffer, &bound, NULL, buf, GEGL_AUTO_ROWSTRIDE);
+     }
+  test_end ("gegl_buffer_set", bound.width * bound.height * ITERATIONS * 16);
+
+
+  test_start ();
+  for (i=0;i<ITERATIONS;i++)
+    {
+      gegl_buffer_get (buffer, 1.0, &bound, NULL, buf, GEGL_AUTO_ROWSTRIDE);
+     }
+  test_end ("gegl_buffer_get", bound.width * bound.height * ITERATIONS * 16);
+
+  g_free (buf);
+  gegl_buffer_destroy (buffer);
+
+  return 0;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]