Skip to content

Commit

Permalink
Fix dhat support for turbo dev and build
Browse files Browse the repository at this point in the history
  • Loading branch information
bgw committed Jan 16, 2025
1 parent 84710d2 commit caa317e
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 82 deletions.
12 changes: 10 additions & 2 deletions crates/napi/src/next_api/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ use super::{
NextTurboTasks, RootTask, TurbopackResult, VcArc,
},
};
use crate::register;
use crate::{register, util::DhatProfilerGuard};

/// Used by [`benchmark_file_io`]. This is a noisy benchmark, so set the
/// threshold high.
Expand Down Expand Up @@ -295,11 +295,19 @@ pub async fn project_new(
turbo_engine_options: NapiTurboEngineOptions,
) -> napi::Result<External<ProjectInstance>> {
register();
let (exit, exit_receiver) = ExitHandler::new_receiver();

if let Some(dhat_profiler) = DhatProfilerGuard::try_init() {
exit.on_exit(async move {
tokio::task::spawn_blocking(move || drop(dhat_profiler))
.await
.unwrap()
});
}

let mut trace = std::env::var("NEXT_TURBOPACK_TRACING")
.ok()
.filter(|v| !v.is_empty());
let (exit, exit_receiver) = ExitHandler::new_receiver();

if cfg!(feature = "tokio-console") && trace.is_none() {
// ensure `trace` is set to *something* so that the `tokio-console` feature works, otherwise
Expand Down
62 changes: 32 additions & 30 deletions crates/napi/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,45 +138,47 @@ pub trait MapErr<T>: Into<Result<T, anyhow::Error>> {

impl<T> MapErr<T> for Result<T, anyhow::Error> {}

/// An opaque type potentially wrapping a [`dhat::Profiler`] instance. If we
/// were not compiled with dhat support, this is an empty struct.
#[cfg(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc"))]
#[napi]
pub fn init_heap_profiler() -> napi::Result<External<RefCell<Option<dhat::Profiler>>>> {
#[cfg(feature = "__internal_dhat-heap")]
{
println!("[dhat-heap]: Initializing heap profiler");
let _profiler = dhat::Profiler::new_heap();
return Ok(External::new(RefCell::new(Some(_profiler))));
}
#[non_exhaustive]
pub struct DhatProfilerGuard(dhat::Profiler);

#[cfg(feature = "__internal_dhat-ad-hoc")]
{
println!("[dhat-ad-hoc]: Initializing ad-hoc profiler");
let _profiler = dhat::Profiler::new_ad_hoc();
return Ok(External::new(RefCell::new(Some(_profiler))));
/// An opaque type potentially wrapping a [`dhat::Profiler`] instance. If we
/// were not compiled with dhat support, this is an empty struct.
///
/// [`dhat::Profiler`]: https://docs.rs/dhat/latest/dhat/struct.Profiler.html
#[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
#[non_exhaustive]
pub struct DhatProfilerGuard;

impl DhatProfilerGuard {
/// Constructs an instance if we were compiled with dhat support.
pub fn try_init() -> Option<Self> {
#[cfg(feature = "__internal_dhat-heap")]
{
println!("[dhat-heap]: Initializing heap profiler");
Some(Self(dhat::Profiler::new_heap()))
}
#[cfg(feature = "__internal_dhat-ad-hoc")]
{
println!("[dhat-ad-hoc]: Initializing ad-hoc profiler");
Some(Self(dhat::Profiler::new_ad_hoc()))
}
#[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
{
None
}
}
}

#[cfg(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc"))]
#[napi]
pub fn teardown_heap_profiler(guard_external: External<RefCell<Option<dhat::Profiler>>>) {
let guard_cell = &*guard_external;

if let Some(guard) = guard_cell.take() {
impl Drop for DhatProfilerGuard {
fn drop(&mut self) {
#[cfg(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc"))]
println!("[dhat]: Teardown profiler");
drop(guard);
}
}

#[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
#[napi]
pub fn init_heap_profiler() -> napi::Result<External<RefCell<Option<u32>>>> {
Ok(External::new(RefCell::new(Some(0))))
}

#[cfg(not(any(feature = "__internal_dhat-heap", feature = "__internal_dhat-ad-hoc")))]
#[napi]
pub fn teardown_heap_profiler(_guard_external: External<RefCell<Option<u32>>>) {}

/// Initialize tracing subscriber to emit traces. This configures subscribers
/// for Trace Event Format <https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview>.
#[napi]
Expand Down
2 changes: 0 additions & 2 deletions packages/next/src/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ import {
loadBindings,
lockfilePatchPromise,
teardownTraceSubscriber,
teardownHeapProfiler,
createDefineEnv,
} from './swc'
import { getNamedRouteRegex } from '../shared/lib/router/utils/route-regex'
Expand Down Expand Up @@ -3796,7 +3795,6 @@ export default async function build(
// Ensure all traces are flushed before finishing the command
await flushAllTraces()
teardownTraceSubscriber()
teardownHeapProfiler()

if (traceUploadUrl && loadedConfig) {
uploadTrace({
Expand Down
5 changes: 1 addition & 4 deletions packages/next/src/build/output/store.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import createStore from 'next/dist/compiled/unistore'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { type Span, flushAllTraces, trace } from '../../trace'
import { teardownHeapProfiler, teardownTraceSubscriber } from '../swc'
import { teardownTraceSubscriber } from '../swc'
import * as Log from './log'

const MAX_LOG_SKIP_DURATION = 500 // 500ms
Expand Down Expand Up @@ -152,7 +152,6 @@ store.subscribe((state) => {
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownHeapProfiler()
return
}

Expand All @@ -176,7 +175,6 @@ store.subscribe((state) => {
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownHeapProfiler()
return
}

Expand Down Expand Up @@ -207,5 +205,4 @@ store.subscribe((state) => {
// Ensure traces are flushed after each compile in development mode
flushAllTraces()
teardownTraceSubscriber()
teardownHeapProfiler()
})
4 changes: 0 additions & 4 deletions packages/next/src/build/swc/generated-native.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,6 @@ export interface NapiRewrite {
missing?: Array<NapiRouteHas>
}
export declare function getTargetTriple(): string
export declare function initHeapProfiler(): ExternalObject<RefCell>
export declare function teardownHeapProfiler(
guardExternal: ExternalObject<RefCell>
): void
/**
* Initialize tracing subscriber to emit traces. This configures subscribers
* for Trace Event Format <https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview>.
Expand Down
39 changes: 1 addition & 38 deletions packages/next/src/build/swc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,6 @@ let wasmBindings: Binding
let downloadWasmPromise: any
let pendingBindings: any
let swcTraceFlushGuard: any
let swcHeapProfilerFlushGuard: any
let downloadNativeBindingsPromise: Promise<void> | undefined = undefined

export const lockfilePatchPromise: { cur?: Promise<void> } = {}
Expand Down Expand Up @@ -1225,8 +1224,6 @@ function loadNative(importPath?: string) {
getTargetTriple: bindings.getTargetTriple,
initCustomTraceSubscriber: bindings.initCustomTraceSubscriber,
teardownTraceSubscriber: bindings.teardownTraceSubscriber,
initHeapProfiler: bindings.initHeapProfiler,
teardownHeapProfiler: bindings.teardownHeapProfiler,
turbo: {
createProject: bindingToApi(customBindings ?? bindings, false),
startTurbopackTraceServer(traceFilePath) {
Expand Down Expand Up @@ -1324,30 +1321,13 @@ export function getBinaryMetadata() {
*
*/
export function initCustomTraceSubscriber(traceFileName?: string) {
if (!swcTraceFlushGuard) {
if (swcTraceFlushGuard) {
// Wasm binary doesn't support trace emission
let bindings = loadNative()
swcTraceFlushGuard = bindings.initCustomTraceSubscriber?.(traceFileName)
}
}

/**
* Initialize heap profiler, if possible.
* Note this is not available in release build of next-swc by default,
* only available by manually building next-swc with specific flags.
* Calling in release build will not do anything.
*/
export function initHeapProfiler() {
try {
if (!swcHeapProfilerFlushGuard) {
let bindings = loadNative()
swcHeapProfilerFlushGuard = bindings.initHeapProfiler?.()
}
} catch (_) {
// Suppress exceptions, this fn allows to fail to load native bindings
}
}

function once(fn: () => void): () => void {
let executed = false

Expand All @@ -1360,23 +1340,6 @@ function once(fn: () => void): () => void {
}
}

/**
* Teardown heap profiler, if possible.
*
* Same as initialization, this is not available in release build of next-swc by default
* and calling it will not do anything.
*/
export const teardownHeapProfiler = once(() => {
try {
let bindings = loadNative()
if (swcHeapProfilerFlushGuard) {
bindings.teardownHeapProfiler?.(swcHeapProfilerFlushGuard)
}
} catch (e) {
// Suppress exceptions, this fn allows to fail to load native bindings
}
})

/**
* Teardown swc's trace subscriber if there's an initialized flush guard exists.
*
Expand Down
2 changes: 0 additions & 2 deletions packages/next/src/build/swc/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ export interface Binding {

initCustomTraceSubscriber?(traceOutFilePath?: string): ExternalObject<RefCell>
teardownTraceSubscriber?(guardExternal: ExternalObject<RefCell>): void
initHeapProfiler?(): ExternalObject<RefCell>
teardownHeapProfiler?(guardExternal: ExternalObject<RefCell>): void
css: {
lightning: {
transform(transformOptions: any): Promise<any>
Expand Down
1 change: 1 addition & 0 deletions turbopack/crates/turbo-tasks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ bench = false
default = []
tokio_tracing = ["tokio/tracing"]
hanging_detection = []
local_resolution = []

[lints]
workspace = true
Expand Down

0 comments on commit caa317e

Please sign in to comment.