Clone in a terminal:
Commit ee4a0b7
Johan Mattsson - 2014-03-22T21:32:37+00:00
ee4a0b7f9307b35e7e8c2d0e78540a1efe9c2828johan.mattsson.m@gmail.com

Benchmark Stroke Benchmark functions for the old stroke code, it took 17.6873s to create 5 strokes of the test path.

Changed files (7)

Diff

diff --git a/libbirdfont/EditPoint.vala b/libbirdfont/EditPoint.valaindex 5607046..b199115 100644--- a/libbirdfont/EditPoint.vala+++ b/libbirdfont/EditPoint.vala@@ -1,5 +1,5 @@ /*-    Copyright (C) 2012 Johan Mattsson+    Copyright (C) 2012, 2013, 2014 Johan Mattsson      This library is free software; you can redistribute it and/or modify      it under the terms of the GNU Lesser General Public License as diff --git a/libbirdfont/FastPath.vala b/libbirdfont/FastPath.valanew file mode 100644index 0000000..1a1d341--- /dev/null+++ b/libbirdfont/FastPath.vala@@ -0,0 +1,138 @@+/*+    Copyright (C) 2014 Johan Mattsson++    This library 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.++    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 +    Lesser General Public License for more details.+*/++namespace BirdFont {+	+/** A faster implementation of the Path and EditPoint classes. */+public class FastPath : GLib.Object {+	+	/** Control points and control point handles.+	 * +	 * Each point is stored with left handle at index - 2,+	 * the point at index, and right handle at index + 2. Both x and y+	 * coordinates is stores in this array.+	 */+	double* points;+	+	/** Point types. */+	uint* types;+	+	/** The number of points that can be stored in the point array. */+	int capacity;+		+	public static const uint NUMBERS_PER_POINT = 6;++	public static const uint LEFT_HANDLE_POS_X = 0;+	public static const uint LEFT_HANDLE_POS_Y = 1;+	public static const uint POS_X = 2;+	public static const uint POS_Y = 3;+	public static const uint RIGHT_HANDLE_POS_X = 4;+	public static const uint RIGHT_HANDLE_POS_Y = 5;++	/** Various boolean properties */+	uint* flags;++	public static uint ACTIVE = 1 << 0;+	public static uint SELECTED = 1 << 1;+	public static uint DELETED = 1 << 2;+	+	public static uint TIE_HANDLES = 1 << 3;+	public static uint REFLECTIVE_HANDLES = 1 << 4;+	+	/** Number of control points in this path. */+	int number_of_points = 0;+	+	public FastPath () {+		capacity = 1024;+		points = new double[capacity * NUMBERS_PER_POINT];+		types = new uint[capacity];+	}++	~FastPath () {+		delete points;+		delete types;+	}+					+	/** @return number of control points in this path. */+	public int get_length () {+		return number_of_points;+	}+	+	/** Get a slow representation for an edipoint. */+	public EditPoint get_editpoint (int index) {+		EditPoint ep = new EditPoint (get_x (index), get_y (index), get_point_type (index));+		ep.get_left_handle ().move_to_coordinate (get_left_handle_x (index), get_left_handle_y (index));+		ep.get_right_handle ().move_to_coordinate (get_right_handle_x (index), get_right_handle_y (index));		+		return ep;+	}++	public void set_editpoint (int index, EditPoint ep) {+		points[NUMBERS_PER_POINT * index + POS_X] = ep.x;+		points[NUMBERS_PER_POINT * index + POS_Y] = ep.y;+		points[NUMBERS_PER_POINT * index + LEFT_HANDLE_POS_X] = ep.get_left_handle ().x ();+		points[NUMBERS_PER_POINT * index + LEFT_HANDLE_POS_Y] = ep.get_left_handle ().y ();+		points[NUMBERS_PER_POINT * index + RIGHT_HANDLE_POS_X] = ep.get_right_handle ().x ();+		points[NUMBERS_PER_POINT * index + RIGHT_HANDLE_POS_Y] = ep.get_right_handle ().y ();+	}++	public double get_x (int index) {+		return points[NUMBERS_PER_POINT * index + POS_X];+	}+	+	public double get_y (int  index) {+		return points[NUMBERS_PER_POINT * index + POS_Y];+	}++	public double get_left_handle_x (int index) {+		return points[NUMBERS_PER_POINT * index + LEFT_HANDLE_POS_X];+	}+	+	public double get_left_handle_y (int  index) {+		return points[NUMBERS_PER_POINT * index + LEFT_HANDLE_POS_Y];+	}++	public double get_right_handle_x (int index) {+		return points[NUMBERS_PER_POINT * index + RIGHT_HANDLE_POS_X];+	}+	+	public double get_right_handle_y (int  index) {+		return points[NUMBERS_PER_POINT * index + RIGHT_HANDLE_POS_Y];+	}+			+	public PointType get_point_type (int index) {+		return (PointType) types[index];+	}++	public bool is_active (int index) {+		return (flags[index] & ACTIVE) > 0;+	}++	public bool is_selected (int index) {+		return (flags[index] & SELECTED) > 0;+	}++	public bool is_deleted (int index) {+		return (flags[index] & DELETED) > 0;+	}++	public bool has_tied_handles (int index) {+		return (flags[index] & TIE_HANDLES) > 0;+	}++	public bool has_reflective_handles (int index) {+		return (flags[index] & REFLECTIVE_HANDLES) > 0;+	}+}++}diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex 59cd820..6bf5bc2 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -27,8 +27,7 @@ public class Path { 	public List<EditPoint> points;  	EditPoint? last_point = null;-	EditPoint? second_last_point = null;-+	 	/** Path boundaries */ 	public double xmax = double.MIN; 	public double xmin = double.MAX;@@ -967,7 +966,6 @@ public class Path { 			} 		} 		-		second_last_point = last_point; 		last_point = p; 		 		return np;diff --git a/libbirdfont/Test.vala b/libbirdfont/Test.valanew file mode 100644index 0000000..2e27748--- /dev/null+++ b/libbirdfont/Test.vala@@ -0,0 +1,47 @@+/*+    Copyright (C) 2012, 2014 Johan Mattsson++    This library 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.++    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 +    Lesser General Public License for more details.+*/++namespace BirdFont {++class Test : Object {+	public Callback callback;+	public string name;+	double time;+	bool benchmark = false;+	+	public Test (Callback callback, string name, bool benchmark = false) {+		this.callback = callback;+		this.name = name;+		this.time = 0;+		this.benchmark = benchmark;+	}+	+	public void timer_start () {+		time = GLib.get_real_time ();+	}++	public void timer_stop () {+		time = GLib.get_real_time () - time;+	}+	+	public double get_time () {+		return time / 1000000.0;+	}+	+	public bool is_benchmark () {+		return benchmark;+	}+}++}diff --git a/libbirdfont/TestBirdFont.vala b/libbirdfont/TestBirdFont.valanew file mode 100644index 0000000..f9327fd--- /dev/null+++ b/libbirdfont/TestBirdFont.vala@@ -0,0 +1,268 @@+/*
+    Copyright (C) 2012, 2014 Johan Mattsson
+
+    This library 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.
+
+    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 
+    Lesser General Public License for more details.
+*/
+
+namespace BirdFont {
+
+/** Class for executing tests cases. */
+class TestBirdFont : GLib.Object {
+
+	const int NOT_STARTED = 0;
+	const int RUNNING = 1;
+	const int PAUSED = 2;
+	const int DONE = 3;
+	
+	static int state = NOT_STARTED;
+
+	TestCases tests;
+	
+	unowned List<Test> test_cases;
+	unowned List<Test?>? current_case = null;
+
+	unowned List<Test> passed;
+	unowned List<Test> failed;
+	unowned List<Test> skipped;
+
+	unowned List<Test> bechmarks;
+
+	static TestBirdFont? singleton = null;
+
+	bool has_failed = false;
+	bool has_skipped = false;
+		
+	static bool slow_test = false;
+	
+	string test_cases_to_run; // name of specific test case or all to run all test cases
+	
+	public TestBirdFont () {
+		assert (singleton == null);
+		tests = new TestCases ();
+		test_cases = tests.get_test_functions ();
+		current_case = test_cases.first ();
+		test_cases_to_run = "All";
+		
+		from_command_line ();
+	}
+	
+	public static bool is_slow_test () {
+		return slow_test;
+	}
+	
+	public static void set_slow_test (bool s) {
+		slow_test = s;
+	}
+	
+	public static TestBirdFont get_singleton () {
+		if (singleton == null) {
+			singleton = new TestBirdFont ();
+		}
+		
+		return (!) singleton;
+	}
+
+	private bool has_test_case (string s) {
+		foreach (var t in test_cases) {
+			if (t.name == s) return true;
+		}	
+		
+		if (s == "" || s == "All") {
+			print ("No specific tescase given run all test cases.\n");
+			return true;
+		}
+		
+		return false;
+	}
+
+	/** Run only test specified on the command line. */
+	private void from_command_line () {
+		string? stn = BirdFont.get_argument ("--test");
+	
+		if (stn != null) {
+			string st = (!) stn;
+			
+			if (!has_test_case (st)) {
+				stderr.printf (@"Test case \"$st\" does not exist.\n");
+				stderr.printf ("\nAvaliable test cases:\n");
+				
+				foreach (var t in test_cases) {
+					stderr.printf (t.name);
+					stderr.printf ("\n");
+				}
+				
+				Process.exit(1);
+			}
+
+			if (st == "All" || st == "") {
+				return;
+			} else {
+				stderr.printf  (@"Run only test case \"$st\" \n");
+			}
+			
+			test_cases_to_run = st;
+		}
+	}
+
+	public static void log (string? log_domain, LogLevelFlags log_levels, string message) {		
+		Test t = (!)((!)get_singleton ().current_case).data;
+		
+		if (log_domain != null) {
+			stderr.printf ("%s: \n", (!) log_domain);
+		}
+		
+		stderr.printf ("Testcase \"%s\" failed because:\n", t.name);
+		stderr.printf ("%s\n\n", message);	
+		
+		get_singleton ().has_failed = true;
+		
+		assert (!BirdFont.fatal_wanings);
+	}
+
+	public static void @continue () {
+		int s = AtomicInt.get (ref state);
+		if (s == DONE) {
+			singleton = null;
+		}
+
+		TestBirdFont t = get_singleton ();
+		
+		LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;
+		Log.set_handler (null, levels, log);
+				
+		AtomicInt.set (ref state, RUNNING);
+		t.run_all_tests ();
+	}
+
+	public static bool is_running () {
+		int r = AtomicInt.get (ref state);
+		return (r == RUNNING);
+	}
+
+	public static void pause () {
+		AtomicInt.set (ref state, PAUSED);
+		Log.set_handler (null, LogLevelFlags.LEVEL_MASK, Log.default_handler);
+	}
+
+	private static void pad (int t) {
+		for (int i = 0; i < t; i++) {
+			stdout.printf (" ");
+		}
+	}
+
+	public void print_result () {
+		stdout.printf ("\n");
+		stdout.printf ("Test case results:\n");
+
+		foreach (Test t in skipped) {
+			stdout.printf ("%s", t.name);
+			pad (40 - t.name.char_count());
+			stdout.printf ("Skipped\n");
+		}
+		
+		if (skipped.length () > 0) {
+			stdout.printf ("\n");
+		}
+		
+		foreach (Test t in passed) {
+			stdout.printf ("%s", t.name);
+			pad (40 - t.name.char_count());
+			stdout.printf ("Passed\n");
+		}
+		
+		foreach (Test t in failed) {
+			stdout.printf ("%s", t.name);
+			pad (40 - t.name.char_count());
+			stdout.printf ("Failed\n");
+		}
+
+		foreach (Test t in bechmarks) {
+			stdout.printf ("%s", t.name);
+			pad (40 - t.name.char_count());
+			stdout.printf (@"$(t.get_time ())s\n");
+		}		
+
+		stdout.printf ("\n");
+		
+		stdout.printf ("Total %u test cases executed, %u passed and %u failed.\n", (passed.length () + failed.length ()), passed.length (), failed.length ());
+	}
+
+	/** Run tests in main loop. */
+	public void run_all_tests () {
+		TimeoutSource idle = new TimeoutSource (20);
+		MenuTab.new_file ();
+		
+		idle.set_callback(() => {
+			int s = AtomicInt.get (ref state);
+			
+			if (s != RUNNING || current_case == null) {
+				return false;
+			}
+
+			Test test = (!)((!) current_case).data;
+					
+			has_failed = false;
+			has_skipped = false;
+
+			if (test_cases_to_run != "All" && test_cases_to_run != test.name) {
+				has_skipped = true;
+			} else {
+				if (test.is_benchmark ()) {
+					test.timer_start ();
+					test.callback ();
+					test.timer_stop ();
+				} else {
+					test.callback ();
+				}
+			}
+			
+			if (test.is_benchmark ()) {
+				bechmarks.append ((!) test);
+			} else if (has_failed) {
+				failed.append ((!) test);
+				
+				if (BirdFont.has_argument ("--exit")) {
+					print_result ();
+					Process.exit (1);
+				}
+	
+			} else if (has_skipped) {
+				skipped.append ((!) test);
+			} else {
+				passed.append ((!) test);
+			}
+
+			if (unlikely (current_case == test_cases.last ())) {
+				stdout.printf ("Finished running test suite.\n");			
+				
+				AtomicInt.set (ref state, DONE);
+				Log.set_handler (null, LogLevelFlags.LEVEL_MASK, Log.default_handler);
+
+				print_result ();
+				
+				if (BirdFont.has_argument ("--exit")) {
+					print_result ();
+					Process.exit ((failed.length () == 0) ? 0 : 1);
+				}
+				return false;
+			}
+			
+			current_case = ((!) current_case).next;
+			
+			return true;
+		});
+    
+		idle.attach (null);
+	}
+
+}
+
+}
diff --git a/libbirdfont/TestCases.vala b/libbirdfont/TestCases.valaindex 92e5386..e33d577 100644--- a/libbirdfont/TestCases.vala+++ b/libbirdfont/TestCases.vala@@ -44,6 +44,12 @@ class TestCases { 		add (test_preview, "Preview"); 		add (test_kerning, "Kerning"); 		add (test_boundaries, "Boundaries");+		+		add_bechmark (benchmark_stroke, "Stroke");+	}+	+	private void add_bechmark (Callback callback, string name) {+		test_cases.append (new Test (callback, name, true)); 	} 	 	private void add (Callback callback, string name) {@@ -53,6 +59,21 @@ class TestCases { 	public unowned List<Test> get_test_functions () { 		return test_cases; 	}++	public static void benchmark_stroke () {+		Glyph glyph;+		test_open_next_glyph ();+		test_illustrator_import ();+		+		glyph = MainWindow.get_current_glyph ();+		for (int i = 0; i < 5; i++) {+			foreach (Path p in glyph.path_list) {+				p.set_stroke (i / 100.0);+				glyph.update_view ();+				Tool.yield ();+			}+		}+	} 	 	public static void test_freetype () { 		StringBuilder? data;diff --git a/libbirdfont/TestSupplement.vala b/libbirdfont/TestSupplement.valadeleted file mode 100644index aca43a6..0000000--- a/libbirdfont/TestSupplement.vala+++ /dev/null@@ -1,260 +0,0 @@-/*
-    Copyright (C) 2012 Johan Mattsson
-
-    This library 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.
-
-    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 
-    Lesser General Public License for more details.
-*/
-
-namespace BirdFont {
-
-class Test : Object {
-	public Callback callback;
-	public string name;
-	
-	public Test (Callback callback, string name) {
-		this.callback = callback;
-		this.name = name;
-	}
-}
-
-/** Class for executing tests cases. */
-class TestBirdFont : GLib.Object {
-
-	const int NOT_STARTED = 0;
-	const int RUNNING = 1;
-	const int PAUSED = 2;
-	const int DONE = 3;
-	
-	static int state = NOT_STARTED;
-
-	TestCases tests;
-	
-	unowned List<Test> test_cases;
-	unowned List<Test?>? current_case = null;
-
-	unowned List<Test> passed;
-	unowned List<Test> failed;
-	unowned List<Test> skipped;
-
-	static TestBirdFont? singleton = null;
-
-	bool has_failed = false;
-	bool has_skipped = false;
-		
-	static bool slow_test = false;
-	
-	string test_cases_to_run; // name of specific test case or all to run all test cases
-	
-	public TestBirdFont () {
-		assert (singleton == null);
-		tests = new TestCases ();
-		test_cases = tests.get_test_functions ();
-		current_case = test_cases.first ();
-		test_cases_to_run = "All";
-		
-		from_command_line ();
-	}
-	
-	public static bool is_slow_test () {
-		return slow_test;
-	}
-	
-	public static void set_slow_test (bool s) {
-		slow_test = s;
-	}
-	
-	public static TestBirdFont get_singleton () {
-		if (singleton == null) {
-			singleton = new TestBirdFont ();
-		}
-		
-		return (!) singleton;
-	}
-
-	private bool has_test_case (string s) {
-		foreach (var t in test_cases) {
-			if (t.name == s) return true;
-		}	
-		
-		if (s == "" || s == "All") {
-			print ("No specific tescase given run all test cases.\n");
-			return true;
-		}
-		
-		return false;
-	}
-
-	/** Run only test specified on the command line. */
-	private void from_command_line () {
-		string? stn = BirdFont.get_argument ("--test");
-	
-		if (stn != null) {
-			string st = (!) stn;
-			
-			if (!has_test_case (st)) {
-				stderr.printf (@"Test case \"$st\" does not exist.\n");
-				stderr.printf ("\nAvaliable test cases:\n");
-				
-				foreach (var t in test_cases) {
-					stderr.printf (t.name);
-					stderr.printf ("\n");
-				}
-				
-				Process.exit(1);
-			}
-
-			if (st == "All" || st == "") {
-				return;
-			} else {
-				stderr.printf  (@"Run only test case \"$st\" \n");
-			}
-			
-			test_cases_to_run = st;
-		}
-	}
-
-	public static void log (string? log_domain, LogLevelFlags log_levels, string message) {		
-		Test t = (!)((!)get_singleton ().current_case).data;
-		
-		if (log_domain != null) {
-			stderr.printf ("%s: \n", (!) log_domain);
-		}
-		
-		stderr.printf ("Testcase \"%s\" failed because:\n", t.name);
-		stderr.printf ("%s\n\n", message);	
-		
-		get_singleton ().has_failed = true;
-		
-		assert (!BirdFont.fatal_wanings);
-	}
-
-	public static void @continue () {
-		int s = AtomicInt.get (ref state);
-		if (s == DONE) {
-			singleton = null;
-		}
-
-		TestBirdFont t = get_singleton ();
-		
-		LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;
-		Log.set_handler (null, levels, log);
-				
-		AtomicInt.set (ref state, RUNNING);
-		t.run_all_tests ();
-	}
-
-	public static bool is_running () {
-		int r = AtomicInt.get (ref state);
-		return (r == RUNNING);
-	}
-
-	public static void pause () {
-		AtomicInt.set (ref state, PAUSED);
-		Log.set_handler (null, LogLevelFlags.LEVEL_MASK, Log.default_handler);
-	}
-
-	private static void pad (int t) {
-		for (int i = 0; i < t; i++) stdout.printf (" ");
-	}
-
-	public void print_result () {
-		stdout.printf ("\n");
-		stdout.printf ("Test case results:\n");
-
-		foreach (var t in skipped) {
-			stdout.printf ("%s", t.name);
-			pad (40 - t.name.char_count());
-			stdout.printf ("Skipped\n");
-		}
-		
-		if (skipped.length () > 0) {
-			stdout.printf ("\n");
-		}
-		
-		foreach (var t in passed) {
-			stdout.printf ("%s", t.name);
-			pad (40 - t.name.char_count());
-			stdout.printf ("Passed\n");
-		}
-		
-		foreach (var t in failed) {
-			stdout.printf ("%s", t.name);
-			pad (40 - t.name.char_count());
-			stdout.printf ("Failed\n");
-		}
-		
-		stdout.printf ("\n");
-		
-		stdout.printf ("Total %u test cases executed, %u passed and %u failed.\n", (passed.length () + failed.length ()), passed.length (), failed.length ());
-	}
-
-	/** Run tests in main loop. */
-	public void run_all_tests () {
-		TimeoutSource idle = new TimeoutSource (20);
-		MenuTab.new_file ();
-		
-		idle.set_callback(() => {
-			int s = AtomicInt.get (ref state);
-			
-			if (s != RUNNING || current_case == null) {
-				return false;
-			}
-
-			Test test = (!)((!) current_case).data;
-					
-			has_failed = false;
-			has_skipped = false;
-
-			if (test_cases_to_run != "All" && test_cases_to_run != test.name) {
-				has_skipped = true;
-			} else {
-				test.callback ();
-			}
-			
-			if (has_failed) {
-				failed.append ((!) test);
-				
-				if (BirdFont.has_argument ("--exit")) {
-					print_result ();
-					Process.exit (1);
-				}
-	
-			} else if (has_skipped) {
-				skipped.append ((!) test);
-			} else {
-				passed.append ((!) test);
-			}
-
-			if (unlikely (current_case == test_cases.last ())) {
-				stdout.printf ("Finished running test suite.\n");			
-				
-				AtomicInt.set (ref state, DONE);
-				Log.set_handler (null, LogLevelFlags.LEVEL_MASK, Log.default_handler);
-
-				print_result ();
-				
-				if (BirdFont.has_argument ("--exit")) {
-					print_result ();
-					Process.exit ((failed.length () == 0) ? 0 : 1);
-				}
-				return false;
-			}
-			
-			current_case = ((!) current_case).next;
-			
-			return true;
-		});
-    
-		idle.attach (null);
-	}
-
-}
-
-}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112