Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get heap statistics from deno #558

Merged
merged 4 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion router-bridge/js-src/plan_worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ declare namespace Deno {
}
}

function memoryUsage(): MemoryUsage {
return Deno.core.ops.op_runtime_memory_usage();
}

let logFunction: (message: string) => void;
declare let logger: {
trace: typeof logFunction;
Expand All @@ -24,6 +28,16 @@ declare let logger: {
error: typeof logFunction;
};

export interface MemoryUsage {
/** 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",
Expand All @@ -32,6 +46,7 @@ enum PlannerEventKind {
Introspect = "Introspect",
Signature = "Signature",
Subgraphs = "Subgraphs",
GetHeapStatistics = "GetHeapStatistics",
}

interface UpdateSchemaEvent {
Expand Down Expand Up @@ -75,13 +90,19 @@ interface Exit {
kind: PlannerEventKind.Exit;
schemaId: number;
}

interface GetHeapStatisticsEvent {
kind: PlannerEventKind.GetHeapStatistics;
}

type PlannerEvent =
| UpdateSchemaEvent
| PlanEvent
| ApiSchemaEvent
| IntrospectEvent
| SignatureEvent
| SubgraphsEvent
| GetHeapStatisticsEvent
| Exit;
type PlannerEventWithId = {
id: string;
Expand All @@ -92,19 +113,26 @@ type WorkerResultWithId = {
id?: string;
payload: WorkerResult;
};

type WorkerResult =
| PlanResult
| ApiSchemaResult
| ExecutionResult
| Map<string, string>
| String;
| String
| MemoryUsageResult;
// Plan result
type PlanResult =
| ExecutionResultWithUsageReporting<QueryPlanResult>
| FatalError;
type ApiSchemaResult = {
schema: string;
};
type MemoryUsageResult = {
heapTotal: number;
heapUsed: number;
external: number;
};

type FatalError = {
errors: (JsError | WorkerGraphQLError)[];
Expand Down Expand Up @@ -252,6 +280,7 @@ async function run() {
try {
const { id, payload: event } = await receive();
messageId = id;

try {
switch (event?.kind) {
case PlannerEventKind.UpdateSchema:
Expand Down Expand Up @@ -290,6 +319,17 @@ async function run() {

await send({ id, payload: subgraphs });
break;
case PlannerEventKind.GetHeapStatistics:
const mem = memoryUsage();

const result: MemoryUsageResult = {
heapTotal: mem.heapTotal,
heapUsed: mem.heapUsed,
external: mem.external,
};

await send({ id, payload: result });
break;
case PlannerEventKind.Exit:
planners.delete(event.schemaId);
if (planners.size == 0) {
Expand Down
35 changes: 34 additions & 1 deletion router-bridge/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,18 @@ where
}
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
/// deno's heap statistics
pub struct HeapStatistics {
/// total size of the heap for V8, in bytes
pub heap_total: u64,
/// amount of the heap used for V8, in bytes
pub heap_used: u64,
/// emory, in bytes, associated with JavaScript objects outside of the JavaScript isolate
pub external: u64,
}

/// A Deno worker backed query Planner.

pub struct Planner<T>
Expand Down Expand Up @@ -586,6 +598,11 @@ where
})
.await
}

/// Get deno's heap statistics
pub async fn get_heap_statistics(&self) -> Result<HeapStatistics, crate::error::Error> {
self.worker.request(PlanCmd::GetHeapStatistics).await
}
}

impl<T> Drop for Planner<T>
Expand Down Expand Up @@ -647,7 +664,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
Expand Down Expand Up @@ -767,8 +787,8 @@ pub struct QueryPlannerDebugConfig {
}
#[cfg(test)]
mod tests {
use futures::stream;
use futures::stream::StreamExt;
use futures::stream::{self};

use std::collections::BTreeMap;

Expand Down Expand Up @@ -1871,6 +1891,19 @@ ofType {
insta::assert_snapshot!(schema);
}
}

#[tokio::test]
async fn heap_statistics() {
let planner =
Planner::<serde_json::Value>::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:?}");
tninesling marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[cfg(test)]
Expand Down
27 changes: 26 additions & 1 deletion router-bridge/src/worker.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::error::Error;
use async_channel::{bounded, Receiver, Sender};
use deno_core::Op;
use deno_core::{op, Extension, OpState};
use deno_core::{v8, Op};
use rand::rngs::StdRng;
use rand::{thread_rng, Rng};
use serde::de::DeserializeOwned;
Expand Down Expand Up @@ -79,6 +79,7 @@ impl JsWorker {
log_warn::DECL,
log_error::DECL,
op_crypto_get_random_values::DECL,
op_runtime_memory_usage::DECL,
]),
op_state_fn: Some(Box::new(move |state| {
state.put(response_sender.clone());
Expand Down Expand Up @@ -302,6 +303,30 @@ fn op_crypto_get_random_values(state: &mut OpState, out: &mut [u8]) -> Result<()
Ok(())
}

// HeapStats stores values from a isolate.get_heap_statistics() call
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct MemoryUsage {
//rss: usize,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

keep or go? (i commented on the release PR just now but it's the same question)

heap_total: usize,
heap_used: usize,
external: usize,
}

// from https://github.com/denoland/deno/blob/897159dc6e1b2319cf2f5f09d8d6cecc0d3175fa/runtime/ops/os/mod.rs#L329
// tested in planner.rs
#[op(v8)]
fn op_runtime_memory_usage(scope: &mut v8::HandleScope<'_>) -> MemoryUsage {
let mut s = v8::HeapStatistics::default();
scope.get_heap_statistics(&mut s);
MemoryUsage {
//rss: rss(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same.

heap_total: s.total_heap_size(),
heap_used: s.used_heap_size(),
external: s.external_memory(),
}
}

#[cfg(test)]
mod worker_tests {
use super::JsWorker;
Expand Down
Loading