diff --git a/apps/app/perf-app/app.ts b/apps/app/perf-app/app.ts
new file mode 100644
index 000000000..b3250bf2d
--- /dev/null
+++ b/apps/app/perf-app/app.ts
@@ -0,0 +1,3 @@
+import * as application from "tns-core-modules/application";
+
+application.start({ moduleName: "perf-app/main-page" });
diff --git a/apps/app/perf-app/flexbox/main-page.ts b/apps/app/perf-app/flexbox/main-page.ts
new file mode 100644
index 000000000..e205b78c7
--- /dev/null
+++ b/apps/app/perf-app/flexbox/main-page.ts
@@ -0,0 +1,64 @@
+import {TabView} from "tns-core-modules/ui/tab-view";
+import * as utils from "tns-core-modules/utils/utils";
+
+const titles = ["Etiam lacinia", "Imperdiet ante", "A interdum", "Quisque tempus", "Sodales viverra"];
+const bodies = [
+ "Vivamus ipsum neque, commodo rutrum finibus sit amet, cursus id sapien.",
+ "Duis et iaculis odio. Class aptent taciti.",
+ "Sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.",
+ "Etiam vitae lacinia purus. Vestibulum laoreet nibh a porta aliquet.",
+ "Vivamus ut eros vitae felis volutpat aliquet.",
+ "Aliquam fermentum mauris consequat hendrerit elementum.",
+ "Nam odio tortor, malesuada congue diam volutpat, placerat ullamcorper risus.",
+ "Curabitur eget nunc viverra justo bibendum rutrum ut nec lectus.",
+ "Pellentesque et lacus vel turpis suscipit posuere sed non sapien.",
+ "Integer eget ornare nunc. In lacinia congue sollicitudin.",
+ "Quisque lobortis quam in risus porttitor, ac laoreet lacus auctor."
+];
+
+const items = [];
+for (var i = 0; i < 64; i++) {
+ items.push({
+ icon: "~/ui-tests-app/flexbox/icons/icon" + (1 + (i % 3)) + ".jpg",
+ title: titles[i % titles.length],
+ body: bodies[i % bodies.length],
+ up: (i * 991) % 100,
+ down: (i * 997) % 100
+ });
+}
+
+export function selectionChanged(args) {
+ clear(args);
+}
+
+let repeaterIds = ["repeaterFlexGrid", "repeaterGrid", "repeaterFlexStack", "repeaterStack"];
+
+export function clear(args) {
+ repeaterIds
+ .map(name => args.object.page.getViewById(name))
+ .forEach(repeater => {
+ repeater.bindingContext = null;
+ });
+
+ args.object.page.getViewById("title").text = "---";
+
+ utils.GC();
+}
+
+export function generate(args) {
+ let tab: TabView = args.object.page.getViewById("tabview");
+ let index = tab.selectedIndex;
+
+ let repeater = args.object.page.getViewById(repeaterIds[index]);
+
+ clear(args);
+ setTimeout(() => {
+ let start = Date.now();
+ repeater.bindingContext = items;
+ setTimeout(() => {
+ let end = Date.now();
+ args.object.page.getViewById("title").text = (end - start).toString();
+ console.log("Duration: " + (end - start));
+ });
+ });
+}
diff --git a/apps/app/perf-app/flexbox/main-page.xml b/apps/app/perf-app/flexbox/main-page.xml
new file mode 100644
index 000000000..0c8de34e4
--- /dev/null
+++ b/apps/app/perf-app/flexbox/main-page.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app/perf-app/main-page.ts b/apps/app/perf-app/main-page.ts
new file mode 100644
index 000000000..1abb7a54b
--- /dev/null
+++ b/apps/app/perf-app/main-page.ts
@@ -0,0 +1,98 @@
+import { EventData, Observable } from "tns-core-modules/data/observable";
+import { WrapLayout } from "tns-core-modules/ui/layouts/wrap-layout";
+import { Page } from "tns-core-modules/ui/page";
+import * as buttonModule from "tns-core-modules/ui/button";
+import * as colorModule from "tns-core-modules/color";
+import * as platform from "tns-core-modules/platform";
+import * as dialogs from "tns-core-modules/ui/dialogs";
+import * as frame from "tns-core-modules/ui/frame";
+
+export function pageLoaded(args: EventData) {
+ let page = args.object;
+ let view = require("ui/core/view");
+
+ let wrapLayout = view.getViewById(page, "wrapLayoutWithExamples");
+
+ let examples: Map = new Map();
+ examples.set("properties", "properties/main-page");
+ examples.set("flexbox", "flexbox/main-page");
+
+ let viewModel = new MainPageViewModel(wrapLayout, examples);
+ page.bindingContext = viewModel;
+}
+
+export class MainPageViewModel extends Observable {
+ private _exampleName: string;
+ private basePath: string = "";
+ private colors = ["#ff0000", "#0000cc", "#33cc33", "#33cc33"];
+
+ public examples: Map = new Map();
+
+ constructor(private panel: WrapLayout, private _examples: Map) {
+ super();
+ // trace.enable();
+ // trace.setCategories(trace.categories.Test);
+ this.examples = _examples;
+
+ if (this.shouldLoadBtns()) {
+ this.loadButtons();
+ }
+ }
+
+ get exampleName(): string {
+ return this._exampleName;
+ }
+
+ set exampleName(value: string) {
+ if (this._exampleName !== value) {
+ this._exampleName = value;
+ this.notifyPropertyChange("exampleName", value)
+ }
+ }
+
+ public loadExample(exampleName: any) {
+ console.log("exampleName EXAMPLE: " + exampleName);
+ this.selectExample(exampleName);
+ }
+
+ private shouldLoadBtns(): boolean {
+ return this.panel.getChildrenCount() <= 0;
+ }
+
+ private selectExample(selectedExample: any) {
+ console.log(" EXAMPLE: " + selectedExample);
+
+ if (this.examples.has(selectedExample)) {
+ frame.topmost().navigate("perf-app/" + this.basePath + this.examples.get(selectedExample));
+ }
+ else {
+ dialogs.alert("Cannot find example: " + selectedExample);
+ }
+ }
+
+ private loadButtons() {
+ var count = 0;
+
+ this.examples.forEach((element, key) => {
+ var btn = new buttonModule.Button();
+
+ if (platform.isAndroid) {
+ btn.style.height = 25;
+ btn.style.fontSize = 10;
+ btn.style.margin = "0";
+ btn.style.padding = "0";
+ } else {
+ btn.style.padding = "5";
+ }
+
+ btn.style.color = new colorModule.Color(this.colors[count++ % 3]);
+ btn.on(buttonModule.Button.tapEvent, function(eventData) {
+ let text = btn.text;
+ this.loadExample(text);
+ }, this);
+
+ btn.text = key;
+ this.panel.addChild(btn)
+ });
+ }
+}
\ No newline at end of file
diff --git a/apps/app/perf-app/main-page.xml b/apps/app/perf-app/main-page.xml
new file mode 100644
index 000000000..33306f0d0
--- /dev/null
+++ b/apps/app/perf-app/main-page.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/app/perf-app/properties/main-page.ts b/apps/app/perf-app/properties/main-page.ts
new file mode 100644
index 000000000..e3ba5c1bf
--- /dev/null
+++ b/apps/app/perf-app/properties/main-page.ts
@@ -0,0 +1,76 @@
+import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
+import { TextView } from "tns-core-modules/ui/text-view";
+import { Button } from "tns-core-modules/ui/button";
+
+import * as tests from "./tests";
+
+const c = [10, 100, 1000, 10000, 100000];
+
+function getStack(stack: StackLayout): StackLayout {
+ let p = new StackLayout();
+ stack.removeChildren();
+ stack.addChild(p);
+ return p;
+}
+
+let runner;
+
+export function onNavigatingFrom() {
+ clearInterval(runner);
+}
+
+export function onTap3(args) {
+ let btn =