Files
react-native/ReactCommon/fabric/core/primitives/RawProps.cpp
T
Valentin Shergin 874f656435 Fabric: Rethinking of prop parsing infra
Summary:
This diff reimplements the prop parsing infrastructure in a part where it interacts with RawProps value.

Local synthetic tests show that the new way is 3x faster but the actual production result is quite unpredictable. MobileLab tests show some improvements about 10-20 ms on iPhone 6.

In short, the new way is faster because it inverts the lookup order and heavily relies on actual data types (and their properties) that we use. The old approach required about 130 hash-map lookups (where the key is `std::string`) to parse a single *Props object.
The new approach prepares concrete-props-specific tables with indexes of coming values ahead of time,  iterates over raw data and puts it into those tables, and then performs a lookup in a very efficient manner.

Reviewed By: JoshuaGross

Differential Revision: D15752968

fbshipit-source-id: 847106e652eb7fc7ef7b99884a6f819ea3b9fd06
2019-06-12 21:35:21 -07:00

97 lines
2.3 KiB
C++

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "RawProps.h"
#include <react/core/RawPropsParser.h>
namespace facebook {
namespace react {
RawProps::RawProps() {
mode_ = Mode::Empty;
}
/*
* Creates an object with given `runtime` and `value`.
*/
RawProps::RawProps(jsi::Runtime &runtime, jsi::Value const &value) noexcept {
if (value.isNull()) {
mode_ = Mode::Empty;
return;
}
mode_ = mode_ = Mode::JSI;
runtime_ = &runtime;
value_ = jsi::Value(runtime, value);
}
/*
* Creates an object with given `folly::dynamic` object.
* Deprecated. Do not use.
* We need this temporary, only because we have a callsite that does not have
* a `jsi::Runtime` behind the data.
*/
RawProps::RawProps(folly::dynamic const &dynamic) noexcept {
if (dynamic.isNull()) {
mode_ = Mode::Empty;
return;
}
mode_ = Mode::Dynamic;
dynamic_ = dynamic;
}
void RawProps::parse(RawPropsParser const &parser) const {
assert(parser_ == nullptr && "A parser was already assigned.");
parser_ = &parser;
parser.preparse(*this);
}
#ifdef ANDROID
/*
* Deprecated. Do not use.
* The support for explicit conversion to `folly::dynamic` is deprecated and
* will be removed as soon Android implementation does not need it.
*/
RawProps::operator folly::dynamic() const noexcept {
switch (mode_) {
case Mode::Empty:
return folly::dynamic::object();
case Mode::JSI:
return jsi::dynamicFromValue(*runtime_, value_);
case Mode::Dynamic:
return dynamic_;
}
}
#endif
/*
* Returns `true` if the object is empty.
* Empty `RawProps` does not have any stored data.
*/
bool RawProps::isEmpty() const noexcept {
return mode_ == Mode::Empty;
}
/*
* Returns a const unowning pointer to `RawValue` of a prop with a given name.
* Returns `nullptr` if a prop with the given name does not exist.
*/
const RawValue *RawProps::at(
char const *name,
char const *prefix,
char const *suffix) const noexcept {
assert(
parser_ &&
"The object is not parsed. `parse` must be called before `at`.");
return parser_->at(*this, RawPropsKey{prefix, name, suffix});
}
} // namespace react
} // namespace facebook