diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 9a636dd45555b901ef415ba56f4b74928fc3653c..d143ed57014146f308d2cd01c030c921eee9ceb1 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -5433,11 +5433,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 ca2f71a588fda02927b6f47c65ce764231dba5fd..760962a2c186b8c4d5ee8809c2de97c46298f237 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
 	//
@@ -657,8 +665,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);
@@ -691,8 +703,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 3a7f867f4e80792654752a202f8ded66e1db36ec..ef898de94a381dc53576eaa75efe475b18e9139f 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 ddd19fac65228f692e3339687ed0975f43f2772d..89b359c5514805c012104524ab7390a98b2cc7ce 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -82,7 +82,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;