From 1a774eb76c1fdb613bc1af8bf70e96a98e85ba79 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Tue, 6 Aug 2024 16:41:15 +0200 Subject: [PATCH] get heap statistics from deno --- router-bridge/js-src/plan_worker.ts | 53 ++++++++++++++++++++++++++++- router-bridge/src/planner.rs | 31 +++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/router-bridge/js-src/plan_worker.ts b/router-bridge/js-src/plan_worker.ts index 23b72407e..0be826b8c 100644 --- a/router-bridge/js-src/plan_worker.ts +++ b/router-bridge/js-src/plan_worker.ts @@ -24,6 +24,19 @@ declare let logger: { error: typeof logFunction; }; +export interface MemoryUsage { + /** The number of bytes of the current Deno's process resident set size, + * which is the amount of memory occupied in main memory (RAM). */ + rss: number; + /** The total size of the heap for V8, in bytes. */ + heapTotal: number; + /** The amount of the heap used for V8, in bytes. */ + heapUsed: number; + /** Memory, in bytes, associated with JavaScript objects outside of the + * JavaScript isolate. */ + external: number; +} + enum PlannerEventKind { UpdateSchema = "UpdateSchema", Plan = "Plan", @@ -32,6 +45,7 @@ enum PlannerEventKind { Introspect = "Introspect", Signature = "Signature", Subgraphs = "Subgraphs", + GetHeapStatistics = "GetHeapStatistics", } interface UpdateSchemaEvent { @@ -75,6 +89,11 @@ interface Exit { kind: PlannerEventKind.Exit; schemaId: number; } + +interface GetHeapStatisticsEvent { + kind: PlannerEventKind.GetHeapStatistics; +} + type PlannerEvent = | UpdateSchemaEvent | PlanEvent @@ -82,6 +101,7 @@ type PlannerEvent = | IntrospectEvent | SignatureEvent | SubgraphsEvent + | GetHeapStatisticsEvent | Exit; type PlannerEventWithId = { id: string; @@ -92,12 +112,14 @@ type WorkerResultWithId = { id?: string; payload: WorkerResult; }; + type WorkerResult = | PlanResult | ApiSchemaResult | ExecutionResult | Map - | String; + | String + | MemoryUsageResult; // Plan result type PlanResult = | ExecutionResultWithUsageReporting @@ -105,6 +127,12 @@ type PlanResult = type ApiSchemaResult = { schema: string; }; +type MemoryUsageResult = { + rss: number; + heapTotal: number; + heapUsed: number; + external: number; +}; type FatalError = { errors: (JsError | WorkerGraphQLError)[]; @@ -290,6 +318,29 @@ async function run() { await send({ id, payload: subgraphs }); break; + case PlannerEventKind.GetHeapStatistics: + logger.info(`received event: ${JSON.stringify(event)}`); + + const mem = Deno.memoryUsage(); + //const mem = memoryUsage(); + + logger.info(`got memoryUsage`); + const result: MemoryUsageResult = { + rss: mem.rss, + heapTotal: mem.heapTotal, + heapUsed: mem.heapUsed, + external: mem.external, + }; + /*const result: MemoryUsageResult = { + rss: 1, + heapTotal: 2, + heapUsed: 3, + external: 4, + };*/ + logger.info(`memoryUsage: ${JSON.stringify(result)}`); + + await send({ id, payload: result }); + break; case PlannerEventKind.Exit: planners.delete(event.schemaId); if (planners.size == 0) { diff --git a/router-bridge/src/planner.rs b/router-bridge/src/planner.rs index 5bdc08fbc..941acae3f 100644 --- a/router-bridge/src/planner.rs +++ b/router-bridge/src/planner.rs @@ -398,6 +398,15 @@ where } } +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct HeapStatistics { + pub rss: u64, + pub heap_total: u64, + pub heap_used: u64, + pub external: u64, +} + /// A Deno worker backed query Planner. pub struct Planner @@ -586,6 +595,11 @@ where }) .await } + + /// Get deno's heap statistics + pub async fn get_heap_statistics(&self) -> Result { + self.worker.request(PlanCmd::GetHeapStatistics).await + } } impl Drop for Planner @@ -647,7 +661,10 @@ enum PlanCmd { Subgraphs { schema_id: u64 }, #[serde(rename_all = "camelCase")] Exit { schema_id: u64 }, + #[serde(rename_all = "camelCase")] + GetHeapStatistics, } + #[derive(Serialize, Debug, Clone, PartialEq, Eq, Hash)] #[serde(rename_all = "camelCase")] /// Query planner configuration @@ -1871,6 +1888,20 @@ ofType { insta::assert_snapshot!(schema); } } + + #[tokio::test] + async fn heap_statistics() { + let planner = + Planner::::new(SCHEMA.to_string(), QueryPlannerConfig::default()) + .await + .unwrap(); + + let _subgraphs = planner.subgraphs().await.unwrap(); + let statistics = planner.get_heap_statistics().await.unwrap(); + + println!("statistics: {statistics:?}"); + panic!() + } } #[cfg(test)]