diff --git a/tests/Makefile.am b/tests/Makefile.am index 4cf093c462..8ad8cb86bd 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -8,7 +8,7 @@ LAT = lat endif -noinst_PROGRAMS = $(LAT) spidey_bench mass_elements +noinst_PROGRAMS = $(LAT) spidey_bench mass_elements complexity AM_CFLAGS = $(GST_OBJ_CFLAGS) LIBS = $(GST_OBJ_LIBS) diff --git a/tests/bench-complexity.scm b/tests/bench-complexity.scm new file mode 100755 index 0000000000..985d0ae530 --- /dev/null +++ b/tests/bench-complexity.scm @@ -0,0 +1,69 @@ +#!/bin/bash +# -*- scheme -*- +exec guile -s $0 "$@" +!# + +;; Quick hack to make some data files that gnuplot can read from +;; complexity. Guile 1.6. + +(use-modules (srfi srfi-13) + (srfi srfi-1) + (ice-9 optargs) + (ice-9 popen)) + +(define *phases* '(create set run destroy)) + +(define (read-lines port) + (let lp ((lines '())) + (let ((x (read-line port))) + (if (eof-object? x) + (begin + (close-port port) + (reverse! lines)) + (lp (cons x lines)))))) + +(define (parse-time str) + (and (char-numeric? (string-ref str 0)) + (fold (lambda (x ret) (+ (* ret 60) x)) 0 + (map (lambda (x) (with-input-from-string x read)) + (string-split str #\:))))) + +(define (run-test program . args) + (format #t "; running test: ~a\n" (cons program args)) + (map + cons + *phases* + (filter-map + parse-time + (read-lines + (open-input-pipe + (string-join (map object->string (cons program args)) " ")))))) + +(define (seq start stop step) + (let lp ((n start) (out '())) + (if (> n stop) + (reverse! out) + (lp (+ n step) (cons n out))))) + +(define (run-tests n-elements) + (let lp ((x 1) (out '())) + (if (> x n-elements) + (reverse! out) + (lp (* x 2) + (acons x (run-test "./complexity" x n-elements) out))))) + +(define (output-results results) + (let ((p (open-output-file "complexity.data"))) + (display "#complexity creation state-change run destroy\n" p) + (for-each + (lambda (line) + (display (car line) p) + (for-each + (lambda (t) (format p " ~a" t)) + (map cdr (cdr line))) + (newline p)) + results) + (close-port p))) + +(output-results + (apply run-tests (map string->number (cdr (program-arguments))))) diff --git a/tests/benchmarks/complexity.c b/tests/benchmarks/complexity.c new file mode 100644 index 0000000000..703aa3230a --- /dev/null +++ b/tests/benchmarks/complexity.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#define BUFFER_COUNT (1000) +#define SRC_ELEMENT "fakesrc" +#define SINK_ELEMENT "fakesink" + + +static GstClockTime +gst_get_current_time (void) +{ + GTimeVal tv; + + g_get_current_time (&tv); + return GST_TIMEVAL_TO_TIME (tv); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *src, *e; + GSList *saved_src_list, *src_list, *new_src_list; + guint complexity_order, n_elements, i, j, max_this_level; + GstClockTime start, end; + gboolean all_srcs_linked; + + gst_init (&argc, &argv); + + if (argc != 3) { + g_print ("usage: %s COMPLEXITY_ORDER N_ELEMENTS\n", argv[0]); + return 1; + } + + complexity_order = atoi (argv[1]); + n_elements = atoi (argv[2]); + + start = gst_get_current_time (); + + pipeline = gst_element_factory_make ("pipeline", NULL); + g_assert (pipeline); + + e = gst_element_factory_make ("fakesrc", NULL); + g_object_set (e, "num-buffers", BUFFER_COUNT, NULL); + g_object_set (e, "silent", TRUE, NULL); + gst_bin_add (GST_BIN (pipeline), e); + src_list = saved_src_list = g_slist_append (NULL, e); + + new_src_list = NULL; + + max_this_level = 1; + j = 0; + i = 0; + all_srcs_linked = FALSE; + for (i = 0, j = 0; i < n_elements; i++, j++) { + if (j >= max_this_level) { + g_slist_free (saved_src_list); + saved_src_list = g_slist_reverse (new_src_list); + new_src_list = NULL; + j = 0; + all_srcs_linked = FALSE; + max_this_level *= complexity_order; + } + + if (!src_list) { + if (j) + all_srcs_linked = TRUE; + src_list = saved_src_list; + } + + src = (GstElement *) src_list->data; + src_list = src_list->next; + + if (i + max_this_level < n_elements) + e = gst_element_factory_make ("tee", NULL); + else + e = gst_element_factory_make ("fakesink", NULL); + g_object_set (e, "silent", TRUE, NULL); + new_src_list = g_slist_prepend (new_src_list, e); + + gst_bin_add (GST_BIN (pipeline), e); + if (gst_element_link (src, e) != GST_PAD_LINK_OK) + g_assert_not_reached (); + } + + g_slist_free (saved_src_list); + g_slist_free (new_src_list); + + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - creating and linking %d elements\n", + GST_TIME_ARGS (end - start), i); + + start = gst_get_current_time (); + if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) + g_assert_not_reached (); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to playing\n", + GST_TIME_ARGS (end - start)); + + start = gst_get_current_time (); + while (gst_bin_iterate (GST_BIN (pipeline))); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - putting %u buffers through\n", + GST_TIME_ARGS (end - start), BUFFER_COUNT); + + start = gst_get_current_time (); + g_object_unref (pipeline); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n", + GST_TIME_ARGS (end - start)); + + return 0; +} diff --git a/tests/benchmarks/complexity.gnuplot b/tests/benchmarks/complexity.gnuplot new file mode 100644 index 0000000000..5cb1a338ec --- /dev/null +++ b/tests/benchmarks/complexity.gnuplot @@ -0,0 +1,9 @@ +set terminal postscript landscape monochrome dashed "Helvetica" 14 +set xlabel "Number of Forks Per Tee" +set ylabel "Seconds" +set logscale x +set title "Complex Pipeline Performance: N Forks per Tee, 1024 Elements" +plot "complexity.data" using 1:2 title "Element creation", \ + "complexity.data" using 1:3 title "State change", \ + "complexity.data" using 1:4 title "Processing 1000 buffers", \ + "complexity.data" using 1:5 title "Element destruction" diff --git a/tests/benchmarks/complexity.scm b/tests/benchmarks/complexity.scm new file mode 100755 index 0000000000..985d0ae530 --- /dev/null +++ b/tests/benchmarks/complexity.scm @@ -0,0 +1,69 @@ +#!/bin/bash +# -*- scheme -*- +exec guile -s $0 "$@" +!# + +;; Quick hack to make some data files that gnuplot can read from +;; complexity. Guile 1.6. + +(use-modules (srfi srfi-13) + (srfi srfi-1) + (ice-9 optargs) + (ice-9 popen)) + +(define *phases* '(create set run destroy)) + +(define (read-lines port) + (let lp ((lines '())) + (let ((x (read-line port))) + (if (eof-object? x) + (begin + (close-port port) + (reverse! lines)) + (lp (cons x lines)))))) + +(define (parse-time str) + (and (char-numeric? (string-ref str 0)) + (fold (lambda (x ret) (+ (* ret 60) x)) 0 + (map (lambda (x) (with-input-from-string x read)) + (string-split str #\:))))) + +(define (run-test program . args) + (format #t "; running test: ~a\n" (cons program args)) + (map + cons + *phases* + (filter-map + parse-time + (read-lines + (open-input-pipe + (string-join (map object->string (cons program args)) " ")))))) + +(define (seq start stop step) + (let lp ((n start) (out '())) + (if (> n stop) + (reverse! out) + (lp (+ n step) (cons n out))))) + +(define (run-tests n-elements) + (let lp ((x 1) (out '())) + (if (> x n-elements) + (reverse! out) + (lp (* x 2) + (acons x (run-test "./complexity" x n-elements) out))))) + +(define (output-results results) + (let ((p (open-output-file "complexity.data"))) + (display "#complexity creation state-change run destroy\n" p) + (for-each + (lambda (line) + (display (car line) p) + (for-each + (lambda (t) (format p " ~a" t)) + (map cdr (cdr line))) + (newline p)) + results) + (close-port p))) + +(output-results + (apply run-tests (map string->number (cdr (program-arguments))))) diff --git a/tests/complexity.c b/tests/complexity.c new file mode 100644 index 0000000000..703aa3230a --- /dev/null +++ b/tests/complexity.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#define BUFFER_COUNT (1000) +#define SRC_ELEMENT "fakesrc" +#define SINK_ELEMENT "fakesink" + + +static GstClockTime +gst_get_current_time (void) +{ + GTimeVal tv; + + g_get_current_time (&tv); + return GST_TIMEVAL_TO_TIME (tv); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *src, *e; + GSList *saved_src_list, *src_list, *new_src_list; + guint complexity_order, n_elements, i, j, max_this_level; + GstClockTime start, end; + gboolean all_srcs_linked; + + gst_init (&argc, &argv); + + if (argc != 3) { + g_print ("usage: %s COMPLEXITY_ORDER N_ELEMENTS\n", argv[0]); + return 1; + } + + complexity_order = atoi (argv[1]); + n_elements = atoi (argv[2]); + + start = gst_get_current_time (); + + pipeline = gst_element_factory_make ("pipeline", NULL); + g_assert (pipeline); + + e = gst_element_factory_make ("fakesrc", NULL); + g_object_set (e, "num-buffers", BUFFER_COUNT, NULL); + g_object_set (e, "silent", TRUE, NULL); + gst_bin_add (GST_BIN (pipeline), e); + src_list = saved_src_list = g_slist_append (NULL, e); + + new_src_list = NULL; + + max_this_level = 1; + j = 0; + i = 0; + all_srcs_linked = FALSE; + for (i = 0, j = 0; i < n_elements; i++, j++) { + if (j >= max_this_level) { + g_slist_free (saved_src_list); + saved_src_list = g_slist_reverse (new_src_list); + new_src_list = NULL; + j = 0; + all_srcs_linked = FALSE; + max_this_level *= complexity_order; + } + + if (!src_list) { + if (j) + all_srcs_linked = TRUE; + src_list = saved_src_list; + } + + src = (GstElement *) src_list->data; + src_list = src_list->next; + + if (i + max_this_level < n_elements) + e = gst_element_factory_make ("tee", NULL); + else + e = gst_element_factory_make ("fakesink", NULL); + g_object_set (e, "silent", TRUE, NULL); + new_src_list = g_slist_prepend (new_src_list, e); + + gst_bin_add (GST_BIN (pipeline), e); + if (gst_element_link (src, e) != GST_PAD_LINK_OK) + g_assert_not_reached (); + } + + g_slist_free (saved_src_list); + g_slist_free (new_src_list); + + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - creating and linking %d elements\n", + GST_TIME_ARGS (end - start), i); + + start = gst_get_current_time (); + if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) + g_assert_not_reached (); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - setting pipeline to playing\n", + GST_TIME_ARGS (end - start)); + + start = gst_get_current_time (); + while (gst_bin_iterate (GST_BIN (pipeline))); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - putting %u buffers through\n", + GST_TIME_ARGS (end - start), BUFFER_COUNT); + + start = gst_get_current_time (); + g_object_unref (pipeline); + end = gst_get_current_time (); + g_print ("%" GST_TIME_FORMAT " - unreffing pipeline\n", + GST_TIME_ARGS (end - start)); + + return 0; +} diff --git a/tests/complexity.gnuplot b/tests/complexity.gnuplot new file mode 100644 index 0000000000..5cb1a338ec --- /dev/null +++ b/tests/complexity.gnuplot @@ -0,0 +1,9 @@ +set terminal postscript landscape monochrome dashed "Helvetica" 14 +set xlabel "Number of Forks Per Tee" +set ylabel "Seconds" +set logscale x +set title "Complex Pipeline Performance: N Forks per Tee, 1024 Elements" +plot "complexity.data" using 1:2 title "Element creation", \ + "complexity.data" using 1:3 title "State change", \ + "complexity.data" using 1:4 title "Processing 1000 buffers", \ + "complexity.data" using 1:5 title "Element destruction"