diff --git a/include/libcamera/internal/egl.h b/include/libcamera/internal/egl.h
index 0e57678e8..8f905416a 100644
--- a/include/libcamera/internal/egl.h
+++ b/include/libcamera/internal/egl.h
@@ -127,6 +127,8 @@ public:
 	void syncOutput();
 	void flushOutput();
 
+	friend class eGLBenchMark;
+
 private:
 	LIBCAMERA_DISABLE_COPY_AND_MOVE(eGL)
 
@@ -152,4 +154,54 @@ private:
 	PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectui64v;
 	PFNGLGENQUERIESPROC glGenQueries;
 };
+
+class eGLBenchMark {
+public:
+	eGLBenchMark() {}
+	~eGLBenchMark() {}
+
+	void init(void)
+	{
+		glGenQueries(1, &glQueryTimeId_); 
+	}
+
+	void begin(eGL &egl)
+	{
+		egl.glBeginQuery(GL_TIME_ELAPSED_EXT, glQueryTimeId_);
+	}
+
+	void end(eGL &egl)
+	{
+		egl.glEndQuery(GL_TIME_ELAPSED_EXT);
+	}
+
+	GLuint64 getTimeElapsedSync(eGL &egl)
+	{
+		// Caution sync will wait until result is available
+		return getTimeElapsed(egl, true);
+	}
+
+	GLuint64 getTimeElapsedAsync(eGL &egl)
+	{
+		return getTimeElapsed(egl, false);
+	}
+
+private:
+	GLuint glQueryTimeId_;
+
+	GLuint64 getTimeElapsed(eGL &egl, bool sync)
+	{
+		GLuint time_elapsed_ns = 0;
+		GLuint available = 0;
+
+		if (!sync)
+			egl.glGetQueryObjectuiv(glQueryTimeId_, GL_QUERY_RESULT_AVAILABLE, &available);
+
+		if (available || sync)
+			egl.glGetQueryObjectui64v(glQueryTimeId_, GL_QUERY_RESULT, &time_elapsed_ns);
+
+		return time_elapsed_ns;
+	}
+};
+
 } //namespace libcamera
