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

improve performance of fiber forking #1743

Merged
merged 19 commits into from
Dec 5, 2023
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
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