Skip to content

Commit

Permalink
perf: ensure same hidden class for op subscribers
Browse files Browse the repository at this point in the history
  • Loading branch information
cartant committed Nov 6, 2020
1 parent 5c9b764 commit 363978e
Showing 1 changed file with 24 additions and 6 deletions.
30 changes: 24 additions & 6 deletions src/internal/operators/OperatorSubscriber.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
/** @prettier */
import { Subscriber } from '../Subscriber';

// Ignore TypeScript's errors about the following methods being protected.
// They're stored here to avoid their needing to be looked up in the
// constructor.
// @ts-ignore
const defaultOnNext = Subscriber.prototype._next;
// @ts-ignore
const defaultOnError = Subscriber.prototype._error;
// @ts-ignore
const defaultOnComplete = Subscriber.prototype._complete;

/**
* A generic helper for allowing operators to be created with a Subscriber and
* use closures to capture neceessary state from the operator function itself.
Expand All @@ -20,13 +30,21 @@ export class OperatorSubscriber<T> extends Subscriber<T> {
*/
constructor(
destination: Subscriber<any>,
onNext?: (value: T) => void,
onError?: (err: any) => void,
onComplete?: () => void,
onNext: (value: T) => void = defaultOnNext,
onError: (err: any) => void = defaultOnError,
onComplete: () => void = defaultOnComplete,
private onUnsubscribe?: () => void
) {
// It's important - for performance reasons - that all of this class's
// members are initialized and that they are always initialized in the same
// order. This will ensure that all OperatorSubscriber instances have the
// same hidden class in V8. This, in turn, will help keep the number of
// hidden classes involved in property accesses within the base class as
// low as possible. If the number of hidden classes involved exceeds four,
// the property accesses will become megamorphic and performance penalties
// will be incurred - i.e. inline caches won't be used.
super(destination);
if (onNext) {
if (onNext !== defaultOnNext) {
this._next = function (value: T) {
try {
onNext(value);
Expand All @@ -35,7 +53,7 @@ export class OperatorSubscriber<T> extends Subscriber<T> {
}
};
}
if (onError) {
if (onError !== defaultOnError) {
this._error = function (err) {
try {
onError(err);
Expand All @@ -47,7 +65,7 @@ export class OperatorSubscriber<T> extends Subscriber<T> {
this.unsubscribe();
};
}
if (onComplete) {
if (onComplete !== defaultOnComplete) {
this._complete = function () {
try {
onComplete();
Expand Down

0 comments on commit 363978e

Please sign in to comment.