Browse Source

Add flexbox chat benchmark (see #498)

And additional profiling zone markers.
Michael Ragazzon 2 years ago
parent
commit
eb1d6ee616

+ 4 - 0
Backends/RmlUi_Backend_SDL_GL3.cpp

@@ -32,6 +32,7 @@
 #include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/Core.h>
 #include <RmlUi/Core/FileInterface.h>
+#include <RmlUi/Core/Profiling.h>
 #include <SDL.h>
 #include <SDL_image.h>
 
@@ -321,4 +322,7 @@ void Backend::PresentFrame()
 
 	data->render_interface.EndFrame();
 	SDL_GL_SwapWindow(data->window);
+
+	// Optional, used to mark frames during performance profiling.
+	RMLUI_FrameMark;
 }

+ 3 - 0
Source/Core/FontEngineDefault/FontFaceHandleDefault.cpp

@@ -27,6 +27,7 @@
  */
 
 #include "FontFaceHandleDefault.h"
+#include "../../../Include/RmlUi/Core/Profiling.h"
 #include "../../../Include/RmlUi/Core/StringUtilities.h"
 #include "../TextureLayout.h"
 #include "FontFaceLayer.h"
@@ -83,6 +84,8 @@ const FontGlyphMap& FontFaceHandleDefault::GetGlyphs() const
 
 int FontFaceHandleDefault::GetStringWidth(const String& string, float letter_spacing, Character prior_character)
 {
+	RMLUI_ZoneScoped;
+
 	int width = 0;
 	for (auto it_string = StringIteratorU8(string); it_string; ++it_string)
 	{

+ 5 - 2
Source/Core/Layout/FlexFormattingContext.cpp

@@ -30,6 +30,7 @@
 #include "../../../Include/RmlUi/Core/ComputedValues.h"
 #include "../../../Include/RmlUi/Core/Element.h"
 #include "../../../Include/RmlUi/Core/ElementScroll.h"
+#include "../../../Include/RmlUi/Core/Profiling.h"
 #include "../../../Include/RmlUi/Core/Types.h"
 #include "ContainerBox.h"
 #include "LayoutDetails.h"
@@ -42,6 +43,7 @@ namespace Rml {
 
 UniquePtr<LayoutBox> FlexFormattingContext::Format(ContainerBox* parent_container, Element* element, const Box* override_initial_box)
 {
+	RMLUI_ZoneScopedC(0xAFAF4F);
 	auto flex_container_box = MakeUnique<FlexContainer>(element, parent_container);
 
 	ElementScroll* element_scroll = element->GetElementScroll();
@@ -135,7 +137,7 @@ struct FlexItem {
 	Size cross;
 	float flex_shrink_factor;
 	float flex_grow_factor;
-	Style::AlignSelf align_self;  // 'Auto' is replaced by container's 'align-items' value
+	Style::AlignSelf align_self; // 'Auto' is replaced by container's 'align-items' value
 
 	float inner_flex_base_size;   // Inner size
 	float flex_base_size;         // Outer size
@@ -234,9 +236,10 @@ void FlexFormattingContext::Format(Vector2f& flex_resulting_content_size, Vector
 	const float cross_size_base_value = (cross_available_size < 0.0f ? 0.0f : cross_available_size);
 
 	// -- Build a list of all flex items with base size information --
+	const int num_flex_children = element_flex->GetNumChildren();
 	Vector<FlexItem> items;
+	items.reserve(num_flex_children);
 
-	const int num_flex_children = element_flex->GetNumChildren();
 	for (int i = 0; i < num_flex_children; i++)
 	{
 		Element* element = element_flex->GetChild(i);

+ 2 - 0
Source/Core/Layout/FormattingContext.cpp

@@ -29,6 +29,7 @@
 #include "FormattingContext.h"
 #include "../../../Include/RmlUi/Core/ComputedValues.h"
 #include "../../../Include/RmlUi/Core/Element.h"
+#include "../../../Include/RmlUi/Core/Profiling.h"
 #include "BlockFormattingContext.h"
 #include "FlexFormattingContext.h"
 #include "LayoutBox.h"
@@ -40,6 +41,7 @@ namespace Rml {
 UniquePtr<LayoutBox> FormattingContext::FormatIndependent(ContainerBox* parent_container, Element* element, const Box* override_initial_box,
 	FormattingContextType backup_context)
 {
+	RMLUI_ZoneScopedC(0xAFAFAF);
 	using namespace Style;
 
 	if (element->IsReplaced())

+ 80 - 0
Tests/Source/Benchmarks/Flexbox.cpp

@@ -30,6 +30,7 @@
 #include <RmlUi/Core/Context.h>
 #include <RmlUi/Core/Element.h>
 #include <RmlUi/Core/ElementDocument.h>
+#include <RmlUi/Core/Profiling.h>
 #include <RmlUi/Core/Types.h>
 #include <doctest.h>
 #include <nanobench.h>
@@ -491,3 +492,82 @@ TEST_CASE("flexbox")
 		document->Close();
 	}
 }
+
+static const String rml_flexbox_chatbox = R"(
+<rml>
+<head>
+	<title>Chat</title>
+    <link type="text/rcss" href="/../Tests/Data/style.rcss"/>
+	<style>
+		body {
+			font-size: 16px;
+			overflow: auto;
+			height: 300px;
+			width: 300px;
+		}
+		#chat {
+			display: flex;
+			flex-direction: column;
+			border: 2px #caa;
+		}
+		#chat > div {
+			word-break: break-word;
+			border: 2px #aac;
+		}
+	</style>
+</head>
+
+<body>
+	<div id="chat"/>
+</body>
+</rml>
+)";
+
+TEST_CASE("flexbox.chat")
+{
+	Context* context = TestsShell::GetContext();
+	REQUIRE(context);
+
+	nanobench::Bench bench;
+	bench.title("Flexbox chat");
+	bench.relative(true);
+	// bench.epochs(100);
+
+	auto MakeFlexItemsRml = [](int number_items, const String& item_text) {
+		String rml;
+		for (int i = 0; i < number_items; i++)
+			rml += "<div>" + item_text + "</div>";
+		return rml;
+	};
+
+	const String short_words =
+		MakeFlexItemsRml(10, "aaaaaaaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaa aaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaa");
+	const String long_words =
+		MakeFlexItemsRml(10, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+	// The flex items will essentially be formatted four times each:
+	//   - Two times during flex formatting, first to get their height, then to do their actual formatting.
+	//   - Then flex formatting is itself done twice, since the body adds a scrollbar, thereby modifying the available width.
+	// The long words take longer to format, since we do a naive approach to breaking up words in ElementText::GenerateLine, making us calculate
+	// string widths repeatedly. Removing the 'word-break' property should make the long word-case much faster.
+	ElementDocument* document = context->LoadDocumentFromMemory(rml_flexbox_chatbox);
+	Element* chat = document->GetElementById("chat");
+	chat->SetInnerRML(short_words + long_words);
+	document->Show();
+	TestsShell::RenderLoop();
+
+	bench.run("Short words", [&] {
+		chat->SetInnerRML(short_words);
+		context->Update();
+		context->Render();
+		RMLUI_FrameMark;
+	});
+	bench.run("Long words", [&] {
+		chat->SetInnerRML(long_words);
+		context->Update();
+		context->Render();
+		RMLUI_FrameMark;
+	});
+
+	document->Close();
+}