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

Make enums to work as part of data structures for C++ TurboModules codegen #36155

Closed
wants to merge 4 commits into from
Closed
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
95 changes: 95 additions & 0 deletions Libraries/WebPerformance/EventCounts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/

import NativePerformanceObserver from './NativePerformanceObserver';
import {warnNoNativePerformanceObserver} from './PerformanceObserver';
import {rawToPerformanceEntryType} from './RawPerformanceEntry';

Choose a reason for hiding this comment

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

  • ⚠️ Libraries/WebPerformance/EventCounts.js line 13 – 'rawToPerformanceEntryType' is defined but never used. (no-unused-vars)


type EventCountsForEachCallbackType =
| (() => void)
| ((value: number) => void)
| ((value: number, key: string) => void)
| ((value: number, key: string, map: Map<string, number>) => void);

/**
* Implementation of the EventCounts Web Performance API
* corresponding to the standard in
* https://www.w3.org/TR/event-timing/#eventcounts
*/
export interface EventCounts {
size: number;

+entries: () => Iterator<[string, number]>;
+forEach: (callback: EventCountsForEachCallbackType) => void;
+get: (key: string) => ?number;
+has: (key: string) => boolean;
+keys: () => Iterator<string>;
+values: () => Iterator<number>;
}

let cachedEventCounts: ?Map<string, number>;

function getCachedEventCounts(): Map<string, number> {
if (cachedEventCounts) {
return cachedEventCounts;
}
if (!NativePerformanceObserver) {
warnNoNativePerformanceObserver();
return new Map();
}

cachedEventCounts = new Map<string, number>(
NativePerformanceObserver.getEventCounts(),
);
// $FlowFixMe[incompatible-call]
global.queueMicrotask(() => {
// To be consistent with the calls to the API from the same task,
// but also not to refetch the data from native too often,
// schedule to invalidate the cache later,
// after the current task is guaranteed to have finished.
cachedEventCounts = null;
});
return cachedEventCounts ?? new Map();
}

// flowlint unsafe-getters-setters:off
export const EventCountsProxy: EventCounts = {
get size(): number {
return getCachedEventCounts().size;
},

set size(value: number) {
throw new TypeError('EventCounts.size property is read-only');
},

entries: (): Iterator<[string, number]> => {
return getCachedEventCounts().entries();
},

forEach: (callback: EventCountsForEachCallbackType) => {
return getCachedEventCounts().forEach(callback);
},

get: (key: string): ?number => {
return getCachedEventCounts().get(key);
},

has: (key: string): boolean => {
return getCachedEventCounts().has(key);
},

keys: (): Iterator<string> => {
return getCachedEventCounts().keys();
},

values: (): Iterator<number> => {
return getCachedEventCounts().values();
},
};
22 changes: 22 additions & 0 deletions Libraries/WebPerformance/NativePerformanceObserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,26 @@ void NativePerformanceObserver::setOnPerformanceEntryCallback(
PerformanceEntryReporter::getInstance().setReportingCallback(callback);
}

void NativePerformanceObserver::logRawEntry(
jsi::Runtime &rt,
RawPerformanceEntry entry) {
PerformanceEntryReporter::getInstance().logEntry(entry);
}

void NativePerformanceObserver::setDurationThreshold(
jsi::Runtime &rt,
int32_t entryType,
double durationThreshold) {
PerformanceEntryReporter::getInstance().setDurationThreshold(
static_cast<PerformanceEntryType>(entryType), durationThreshold);
}

std::vector<std::pair<std::string, uint32_t>>
NativePerformanceObserver::getEventCounts(jsi::Runtime &rt) {
const auto &eventCounts =
PerformanceEntryReporter::getInstance().getEventCounts();
return std::vector<std::pair<std::string, uint32_t>>(
eventCounts.begin(), eventCounts.end());
}

} // namespace facebook::react
10 changes: 10 additions & 0 deletions Libraries/WebPerformance/NativePerformanceObserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ class NativePerformanceObserver
jsi::Runtime &rt,
std::optional<AsyncCallback<>> callback);

void logRawEntry(jsi::Runtime &rt, RawPerformanceEntry entry);

void setDurationThreshold(
jsi::Runtime &rt,
int32_t entryType,
double durationThreshold);

std::vector<std::pair<std::string, uint32_t>> getEventCounts(
jsi::Runtime &rt);

private:
};

Expand Down
13 changes: 6 additions & 7 deletions Libraries/WebPerformance/NativePerformanceObserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,6 @@ import type {TurboModule} from '../TurboModule/RCTExport';

import * as TurboModuleRegistry from '../TurboModule/TurboModuleRegistry';

export const RawPerformanceEntryTypeValues = {
UNDEFINED: 0,
MARK: 1,
MEASURE: 2,
EVENT: 3,
};

export type RawPerformanceEntryType = number;

export type RawPerformanceEntry = {|
Expand All @@ -42,6 +35,12 @@ export interface Spec extends TurboModule {
+stopReporting: (entryType: RawPerformanceEntryType) => void;
+popPendingEntries: () => GetPendingEntriesResult;
+setOnPerformanceEntryCallback: (callback?: () => void) => void;
+logRawEntry: (entry: RawPerformanceEntry) => void;
+setDurationThreshold: (
entryType: RawPerformanceEntryType,
durationThreshold: number,
) => void;
+getEventCounts: () => $ReadOnlyArray<[string, number]>;
}

export default (TurboModuleRegistry.get<Spec>(
Expand Down
6 changes: 5 additions & 1 deletion Libraries/WebPerformance/Performance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
* @flow strict
*/

import type {EventCounts} from './EventCounts';
import type {HighResTimeStamp} from './PerformanceEntry';

import warnOnce from '../Utilities/warnOnce';
import {EventCountsProxy} from './EventCounts';
import NativePerformance from './NativePerformance';
import {PerformanceEntry} from './PerformanceEntry';

Expand Down Expand Up @@ -83,9 +85,11 @@ function warnNoNativePerformance() {
/**
* Partial implementation of the Performance interface for RN,
* corresponding to the standard in
* https://www.w3.org/TR/user-timing/#extensions-performance-interface
* https://www.w3.org/TR/user-timing/#extensions-performance-interface
*/
export default class Performance {
eventCounts: EventCounts = EventCountsProxy;

mark(
markName: string,
markOptions?: PerformanceMarkOptions,
Expand Down
23 changes: 21 additions & 2 deletions Libraries/WebPerformance/PerformanceEntryReporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,17 @@ void PerformanceEntryReporter::setReportingCallback(
}

void PerformanceEntryReporter::startReporting(PerformanceEntryType entryType) {
reportingType_[static_cast<int>(entryType)] = true;
int entryTypeIdx = static_cast<int>(entryType);
reportingType_[entryTypeIdx] = true;
durationThreshold_[entryTypeIdx] = DEFAULT_DURATION_THRESHOLD;
}

void PerformanceEntryReporter::setDurationThreshold(
PerformanceEntryType entryType,
double durationThreshold) {
durationThreshold_[static_cast<int>(entryType)] = durationThreshold;
}

void PerformanceEntryReporter::stopReporting(PerformanceEntryType entryType) {
reportingType_[static_cast<int>(entryType)] = false;
}
Expand All @@ -47,7 +56,17 @@ GetPendingEntriesResult PerformanceEntryReporter::popPendingEntries() {
}

void PerformanceEntryReporter::logEntry(const RawPerformanceEntry &entry) {
if (!isReportingType(static_cast<PerformanceEntryType>(entry.entryType))) {
const auto entryType = static_cast<PerformanceEntryType>(entry.entryType);
if (entryType == PerformanceEntryType::EVENT) {
eventCounts_[entry.name]++;
}

if (!isReportingType(entryType)) {
return;
}

if (entry.duration < durationThreshold_[entry.entryType]) {
// The entries duration is lower than the desired reporting threshold, skip
return;
}

Expand Down
12 changes: 12 additions & 0 deletions Libraries/WebPerformance/PerformanceEntryReporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ using PerformanceMarkRegistryType = std::
// memory for the sake of the "Performance.measure" mark name lookup
constexpr size_t MARKS_BUFFER_SIZE = 1024;

constexpr double DEFAULT_DURATION_THRESHOLD = 0.0;

enum class PerformanceEntryType {
UNDEFINED = 0,
MARK = 1,
Expand All @@ -66,6 +68,9 @@ class PerformanceEntryReporter : public EventLogger {
void setReportingCallback(std::optional<AsyncCallback<>> callback);
void startReporting(PerformanceEntryType entryType);
void stopReporting(PerformanceEntryType entryType);
void setDurationThreshold(
PerformanceEntryType entryType,
double durationThreshold);

GetPendingEntriesResult popPendingEntries();
void logEntry(const RawPerformanceEntry &entry);
Expand Down Expand Up @@ -102,6 +107,10 @@ class PerformanceEntryReporter : public EventLogger {
void onEventDispatch(EventTag tag) override;
void onEventEnd(EventTag tag) override;

const std::unordered_map<std::string, uint32_t> &getEventCounts() const {
return eventCounts_;
}

private:
PerformanceEntryReporter() {}

Expand All @@ -117,6 +126,9 @@ class PerformanceEntryReporter : public EventLogger {
std::vector<RawPerformanceEntry> entries_;
std::mutex entriesMutex_;
std::array<bool, (size_t)PerformanceEntryType::_COUNT> reportingType_{false};
std::array<double, (size_t)PerformanceEntryType::_COUNT> durationThreshold_{
DEFAULT_DURATION_THRESHOLD};
std::unordered_map<std::string, uint32_t> eventCounts_;

// Mark registry for "measure" lookup
PerformanceMarkRegistryType marksRegistry_;
Expand Down
Loading