Skip to content

Commit

Permalink
improve performance of fiber forking (#1743)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Dec 5, 2023
1 parent bd3432c commit 143ee1e
Show file tree
Hide file tree
Showing 47 changed files with 1,023 additions and 438 deletions.
5 changes: 5 additions & 0 deletions .changeset/chilled-hotels-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

prefer Date.now() over new Date().getTime()
5 changes: 5 additions & 0 deletions .changeset/dirty-cheetahs-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

rename FiberRefs.updatedAs to FiberRef.updateAs
5 changes: 5 additions & 0 deletions .changeset/gorgeous-knives-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

add FiberRefs.updateManyAs
5 changes: 5 additions & 0 deletions .changeset/light-badgers-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

short circuit for empty patches
5 changes: 5 additions & 0 deletions .changeset/red-flowers-pull.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

use native js data types for Metrics
5 changes: 5 additions & 0 deletions .changeset/smart-horses-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

replace use of throw in fiber runtime
5 changes: 5 additions & 0 deletions .changeset/smooth-plants-obey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

optimize FiberRef.update/forkAs
5 changes: 5 additions & 0 deletions .changeset/weak-steaks-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

optimize MutableHashMap
5 changes: 5 additions & 0 deletions examples/fork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Effect } from "effect"

for (let i = 0; i < 200000; i++) {
Effect.runFork(Effect.unit)
}
36 changes: 36 additions & 0 deletions src/Differ.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as ContextPatch from "./internal/differ/contextPatch.js"
import * as HashMapPatch from "./internal/differ/hashMapPatch.js"
import * as HashSetPatch from "./internal/differ/hashSetPatch.js"
import * as OrPatch from "./internal/differ/orPatch.js"
import * as ReadonlyArrayPatch from "./internal/differ/readonlyArrayPatch.js"
import type * as Types from "./Types.js"

/**
Expand Down Expand Up @@ -63,6 +64,8 @@ const ContextPatchTypeId: unique symbol = ContextPatch.ContextPatchTypeId as Dif
const HashMapPatchTypeId: unique symbol = HashMapPatch.HashMapPatchTypeId as Differ.HashMap.TypeId
const HashSetPatchTypeId: unique symbol = HashSetPatch.HashSetPatchTypeId as Differ.HashSet.TypeId
const OrPatchTypeId: unique symbol = OrPatch.OrPatchTypeId as Differ.Or.TypeId
const ReadonlyArrayPatchTypeId: unique symbol = ReadonlyArrayPatch
.ReadonlyArrayPatchTypeId as Differ.ReadonlyArray.TypeId

/**
* @since 2.0.0
Expand Down Expand Up @@ -186,6 +189,29 @@ export declare namespace Differ {
}
}
}

/**
* @since 2.0.0
*/
export namespace ReadonlyArray {
/**
* @since 2.0.0
* @category symbol
*/
export type TypeId = typeof ReadonlyArrayPatchTypeId
/**
* A patch which describes updates to a ReadonlyArray of values.
*
* @since 2.0.0
* @category models
*/
export interface Patch<in out Value, in out Patch> extends Equal {
readonly [ReadonlyArrayPatchTypeId]: {
readonly _Value: Types.Invariant<Value>
readonly _Patch: Types.Invariant<Patch>
}
}
}
}

/**
Expand Down Expand Up @@ -352,6 +378,16 @@ export const orElseEither: {
>
} = internal.orElseEither

/**
* Constructs a differ that knows how to diff a `ReadonlyArray` of values.
*
* @since 2.0.0
* @category constructors
*/
export const readonlyArray: <Value, Patch>(
differ: Differ<Value, Patch>
) => Differ<ReadonlyArray<Value>, Differ.ReadonlyArray.Patch<Value, Patch>> = internal.readonlyArray

/**
* Transforms the type of values that this differ knows how to differ using
* the specified functions that map the new and old value types to each other.
Expand Down
23 changes: 1 addition & 22 deletions src/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4589,17 +4589,6 @@ export const labelMetrics: {
<R, E, A>(self: Effect<R, E, A>, labels: Iterable<MetricLabel.MetricLabel>): Effect<R, E, A>
} = effect.labelMetrics

/**
* Tags each metric in this effect with the specific tag.
*
* @since 2.0.0
* @category metrics
*/
export const labelMetricsSet: {
(labels: HashSet.HashSet<MetricLabel.MetricLabel>): <R, E, A>(self: Effect<R, E, A>) => Effect<R, E, A>
<R, E, A>(self: Effect<R, E, A>, labels: HashSet.HashSet<MetricLabel.MetricLabel>): Effect<R, E, A>
} = effect.labelMetricsSet

/**
* Tags each metric in a scope with a the specific tag.
*
Expand All @@ -4619,23 +4608,13 @@ export const labelMetricsScoped: (
labels: ReadonlyArray<MetricLabel.MetricLabel>
) => Effect<Scope.Scope, never, void> = fiberRuntime.labelMetricsScoped

/**
* Tags each metric in a scope with a the specific tag.
*
* @since 2.0.0
* @category metrics
*/
export const labelMetricsScopedSet: (
labels: HashSet.HashSet<MetricLabel.MetricLabel>
) => Effect<Scope.Scope, never, void> = fiberRuntime.labelMetricsScopedSet

/**
* Retrieves the metric labels associated with the current scope.
*
* @since 2.0.0
* @category metrics
*/
export const metricLabels: Effect<never, never, HashSet.HashSet<MetricLabel.MetricLabel>> = core.metricLabels
export const metricLabels: Effect<never, never, ReadonlyArray<MetricLabel.MetricLabel>> = core.metricLabels

/**
* @since 2.0.0
Expand Down
2 changes: 1 addition & 1 deletion src/FiberRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ export const currentSupervisor: FiberRef<Supervisor.Supervisor<any>> = fiberRunt
* @since 2.0.0
* @category fiberRefs
*/
export const currentMetricLabels: FiberRef<HashSet.HashSet<MetricLabel.MetricLabel>> = core.currentMetricLabels
export const currentMetricLabels: FiberRef<ReadonlyArray<MetricLabel.MetricLabel>> = core.currentMetricLabels

/**
* @since 2.0.0
Expand Down
48 changes: 46 additions & 2 deletions src/FiberRefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ export const setAll: (self: FiberRefs) => Effect.Effect<never, never, void> = in
* @since 2.0.0
* @category utils
*/
export const updatedAs: {
export const updateAs: {
<A>(
options: {
readonly fiberId: FiberId.Runtime
Expand All @@ -139,7 +139,51 @@ export const updatedAs: {
readonly value: A
}
): FiberRefs
} = internal.updatedAs
} = internal.updateAs

/**
* Updates the values of the specified `FiberRef` & value pairs using the provided `FiberId`
*
* @since 2.0.0
* @category utils
*/
export const updateManyAs: {
(
options: {
readonly forkAs?: FiberId.Runtime | undefined
readonly entries: readonly [
readonly [
FiberRef.FiberRef<any>,
readonly [readonly [FiberId.Runtime, any], ...Array<readonly [FiberId.Runtime, any]>]
],
...Array<
readonly [
FiberRef.FiberRef<any>,
readonly [readonly [FiberId.Runtime, any], ...Array<readonly [FiberId.Runtime, any]>]
]
>
]
}
): (self: FiberRefs) => FiberRefs
(
self: FiberRefs,
options: {
readonly forkAs?: FiberId.Runtime | undefined
readonly entries: readonly [
readonly [
FiberRef.FiberRef<any>,
readonly [readonly [FiberId.Runtime, any], ...Array<readonly [FiberId.Runtime, any]>]
],
...Array<
readonly [
FiberRef.FiberRef<any>,
readonly [readonly [FiberId.Runtime, any], ...Array<readonly [FiberId.Runtime, any]>]
]
>
]
}
): FiberRefs
} = internal.updateManyAs

/**
* Note: it will not copy the provided Map, make sure to provide a fresh one.
Expand Down
22 changes: 10 additions & 12 deletions src/Metric.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
/**
* @since 2.0.0
*/
import type * as Chunk from "./Chunk.js"
import type * as Duration from "./Duration.js"
import type * as Effect from "./Effect.js"
import type { LazyArg } from "./Function.js"
import type * as HashSet from "./HashSet.js"
import * as fiberRuntime from "./internal/fiberRuntime.js"
import * as internal from "./internal/metric.js"
import type * as MetricBoundaries from "./MetricBoundaries.js"
Expand Down Expand Up @@ -56,8 +54,8 @@ export interface Metric<in out Type, in In, out Out> extends Metric.Variance<Typ
* `MetricKeyType.Counter` or `MetricKeyType.Gauge`.
*/
readonly keyType: Type
unsafeUpdate(input: In, extraTags: HashSet.HashSet<MetricLabel.MetricLabel>): void
unsafeValue(extraTags: HashSet.HashSet<MetricLabel.MetricLabel>): Out
unsafeUpdate(input: In, extraTags: ReadonlyArray<MetricLabel.MetricLabel>): void
unsafeValue(extraTags: ReadonlyArray<MetricLabel.MetricLabel>): Out
register(): this
<R, E, A extends In>(effect: Effect.Effect<R, E, A>): Effect.Effect<R, E, A>
}
Expand All @@ -69,8 +67,8 @@ export interface Metric<in out Type, in In, out Out> extends Metric.Variance<Typ
export interface MetricApply {
<Type, In, Out>(
keyType: Type,
unsafeUpdate: (input: In, extraTags: HashSet.HashSet<MetricLabel.MetricLabel>) => void,
unsafeValue: (extraTags: HashSet.HashSet<MetricLabel.MetricLabel>) => Out
unsafeUpdate: (input: In, extraTags: ReadonlyArray<MetricLabel.MetricLabel>) => void,
unsafeValue: (extraTags: ReadonlyArray<MetricLabel.MetricLabel>) => Out
): Metric<Type, In, Out>
}

Expand Down Expand Up @@ -357,7 +355,7 @@ export const set: {
* @since 2.0.0
* @category getters
*/
export const snapshot: Effect.Effect<never, never, HashSet.HashSet<MetricPair.MetricPair.Untyped>> = internal.snapshot
export const snapshot: Effect.Effect<never, never, ReadonlyArray<MetricPair.MetricPair.Untyped>> = internal.snapshot

/**
* Creates a metric that ignores input and produces constant output.
Expand Down Expand Up @@ -396,7 +394,7 @@ export const sync: <Out>(evaluate: LazyArg<Out>) => Metric<void, unknown, Out> =
* maxAge: "60 seconds", // Retain observations for 60 seconds.
* maxSize: 1000, // Keep a maximum of 1000 observations.
* error: 0.01, // Allow a 1% error when calculating quantiles.
* quantiles: Chunk.make(0.5, 0.9, 0.99), // Calculate 50th, 90th, and 99th percentiles.
* quantiles: [0.5, 0.9, 0.99], // Calculate 50th, 90th, and 99th percentiles.
* description: "Measures the distribution of response times."
* });
*
Expand All @@ -409,7 +407,7 @@ export const summary: (
readonly maxAge: Duration.DurationInput
readonly maxSize: number
readonly error: number
readonly quantiles: Chunk.Chunk<number>
readonly quantiles: ReadonlyArray<number>
readonly description?: string | undefined
}
) => Metric.Summary<number> = internal.summary
Expand All @@ -424,7 +422,7 @@ export const summaryTimestamp: (
readonly maxAge: Duration.DurationInput
readonly maxSize: number
readonly error: number
readonly quantiles: Chunk.Chunk<number>
readonly quantiles: ReadonlyArray<number>
readonly description?: string | undefined
}
) => Metric.Summary<readonly [value: number, timestamp: number]> // readonly because contravariant
Expand Down Expand Up @@ -498,7 +496,7 @@ export const timer: (
*/
export const timerWithBoundaries: (
name: string,
boundaries: Chunk.Chunk<number>,
boundaries: ReadonlyArray<number>,
description?: string
) => Metric<MetricKeyType.MetricKeyType.Histogram, Duration.Duration, MetricState.MetricState.Histogram> =
internal.timerWithBoundaries
Expand Down Expand Up @@ -723,7 +721,7 @@ export const zip: {
* @since 2.0.0
* @category unsafe
*/
export const unsafeSnapshot: (_: void) => HashSet.HashSet<MetricPair.MetricPair.Untyped> = internal.unsafeSnapshot
export const unsafeSnapshot: (_: void) => ReadonlyArray<MetricPair.MetricPair.Untyped> = internal.unsafeSnapshot

/**
* @since 2.0.0
Expand Down
5 changes: 2 additions & 3 deletions src/MetricBoundaries.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* @since 2.0.0
*/
import type * as Chunk from "./Chunk.js"
import type * as Equal from "./Equal.js"
import * as internal from "./internal/metric/boundaries.js"
import type { Pipeable } from "./Pipeable.js"
Expand All @@ -24,7 +23,7 @@ export type MetricBoundariesTypeId = typeof MetricBoundariesTypeId
*/
export interface MetricBoundaries extends Equal.Equal, Pipeable {
readonly [MetricBoundariesTypeId]: MetricBoundariesTypeId
readonly values: Chunk.Chunk<number>
readonly values: ReadonlyArray<number>
}

/**
Expand All @@ -37,7 +36,7 @@ export const isMetricBoundaries: (u: unknown) => u is MetricBoundaries = interna
* @since 2.0.0
* @category constructors
*/
export const fromChunk: (chunk: Chunk.Chunk<number>) => MetricBoundaries = internal.fromChunk
export const fromIterable: (iterable: Iterable<number>) => MetricBoundaries = internal.fromIterable

/**
* A helper method to create histogram bucket boundaries for a histogram
Expand Down
Loading

0 comments on commit 143ee1e

Please sign in to comment.