diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 8c8dad4ccde14bca3a865b56e21480e037b6f5f3..51c3156f8474dd46b8a88088e6597a286a4fa45e 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -5427,11 +5427,15 @@ void TryRunTics(tic_t realtics)
 			{
 				DEBFILE(va("============ Running tic %d (local %d)\n", gametic, localgametic));
 
+				rs_tictime = I_GetTimeMicros();
+
 				G_Ticker((gametic % NEWTICRATERATIO) == 0);
 				ExtraDataTicker();
 				gametic++;
 				consistancy[gametic%BACKUPTICS] = Consistancy();
 
+				rs_tictime = I_GetTimeMicros() - rs_tictime;
+
 				// Leave a certain amount of tics present in the net buffer as long as we've ran at least one tic this frame.
 				if (client && gamestate == GS_LEVEL && leveltime > 3 && neededtic <= gametic + cv_netticbuffer.value)
 					break;
diff --git a/src/d_main.c b/src/d_main.c
index 25209de68c772a05c0b5827cabe8f67dcdc35ac1..fcc22b4971a7c95f8e51dc9bc1f2daac4063fa44 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -495,6 +495,8 @@ static void D_Display(void)
 				lastdraw = false;
 			}
 
+			rs_uitime = I_GetTimeMicros();
+
 			if (gamestate == GS_LEVEL)
 			{
 				ST_Drawer();
@@ -504,6 +506,10 @@ static void D_Display(void)
 			else
 				F_TitleScreenDrawer();
 		}
+		else
+		{
+			rs_uitime = I_GetTimeMicros();
+		}
 	}
 
 	// change gamma if needed
@@ -544,6 +550,8 @@ static void D_Display(void)
 
 	CON_Drawer();
 
+	rs_uitime = I_GetTimeMicros() - rs_uitime;
+
 	//
 	// wipe update
 	//
@@ -656,8 +664,12 @@ static void D_Display(void)
 				V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
 				snprintf(s, sizeof s - 1, "sdrw %d", rs_hw_spritedrawtime / divisor);
 				V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
-				snprintf(s, sizeof s - 1, "fin  %d", rs_swaptime / divisor);
+				snprintf(s, sizeof s - 1, "ui   %d", rs_uitime / divisor);
 				V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
+				snprintf(s, sizeof s - 1, "fin  %d", rs_swaptime / divisor);
+				V_DrawThinString(30, 90, V_MONOSPACE | V_YELLOWMAP, s);
+				snprintf(s, sizeof s - 1, "tic  %d", rs_tictime / divisor);
+				V_DrawThinString(30, 105, V_MONOSPACE | V_GRAYMAP, s);
 				if (cv_glbatching.value)
 				{
 					snprintf(s, sizeof s - 1, "bsrt %d", rs_hw_batchsorttime / divisor);
@@ -689,8 +701,12 @@ static void D_Display(void)
 				V_DrawThinString(30, 50, V_MONOSPACE | V_YELLOWMAP, s);
 				snprintf(s, sizeof s - 1, "mskd %d", rs_sw_maskedtime / divisor);
 				V_DrawThinString(30, 60, V_MONOSPACE | V_YELLOWMAP, s);
-				snprintf(s, sizeof s - 1, "fin  %d", rs_swaptime / divisor);
+				snprintf(s, sizeof s - 1, "ui   %d", rs_uitime / divisor);
 				V_DrawThinString(30, 70, V_MONOSPACE | V_YELLOWMAP, s);
+				snprintf(s, sizeof s - 1, "fin  %d", rs_swaptime / divisor);
+				V_DrawThinString(30, 80, V_MONOSPACE | V_YELLOWMAP, s);
+				snprintf(s, sizeof s - 1, "tic  %d", rs_tictime / divisor);
+				V_DrawThinString(30, 95, V_MONOSPACE | V_GRAYMAP, s);
 			}
 		}
 
diff --git a/src/r_main.c b/src/r_main.c
index 4f79dd8db4a445b40a5340dc07b9e5812901f444..46ba0ecad1e42d54df113c1d33ac440f464be8aa 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -102,7 +102,9 @@ extracolormap_t *extra_colormaps = NULL;
 // Render stats
 int rs_prevframetime = 0;
 int rs_rendercalltime = 0;
+int rs_uitime = 0;
 int rs_swaptime = 0;
+int rs_tictime = 0;
 
 int rs_bsptime = 0;
 
diff --git a/src/r_main.h b/src/r_main.h
index 729ec6973d595ee71ab1b59fbf2389cf62f6eb2d..f95e2538d18120d8bc64d91987d7e2a1dfaf61e1 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -81,7 +81,9 @@ extern consvar_t cv_renderstats;
 
 extern int rs_prevframetime;// time when previous frame was rendered
 extern int rs_rendercalltime;
+extern int rs_uitime;
 extern int rs_swaptime;
+extern int rs_tictime;
 
 extern int rs_bsptime;