Shift fetching litho attributes to background thread
Summary: Due to litho component instances being immutable we are able to process them later if we hold on to the instance. We have added a Maybe deferred type which sort of resembles a Monad. It wraps a value which may or may not be calculated later. Reviewed By: lblasa Differential Revision: D41474251 fbshipit-source-id: 2ba6e688518dba55cf4aa5ba53f390a92cf0921f
This commit is contained in:
committed by
Facebook GitHub Bot
parent
c95c59342e
commit
7ec09b4f95
@@ -15,6 +15,8 @@ import com.facebook.flipper.plugins.uidebugger.litho.descriptors.props.LayoutPro
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.Deferred
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
import com.facebook.litho.DebugComponent
|
import com.facebook.litho.DebugComponent
|
||||||
|
|
||||||
class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescriptor<DebugComponent> {
|
class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescriptor<DebugComponent> {
|
||||||
@@ -67,19 +69,20 @@ class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescripto
|
|||||||
private val UserPropsId =
|
private val UserPropsId =
|
||||||
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "Litho Props")
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "Litho Props")
|
||||||
|
|
||||||
override fun getData(node: DebugComponent): Map<MetadataId, InspectableObject> {
|
override fun getData(node: DebugComponent): MaybeDeferred<Map<MetadataId, InspectableObject>> {
|
||||||
|
return Deferred {
|
||||||
|
val attributeSections = mutableMapOf<MetadataId, InspectableObject>()
|
||||||
|
|
||||||
val attributeSections = mutableMapOf<MetadataId, InspectableObject>()
|
val layoutProps = LayoutPropExtractor.getProps(node)
|
||||||
|
attributeSections[LayoutId] = InspectableObject(layoutProps.toMap())
|
||||||
|
|
||||||
val layoutProps = LayoutPropExtractor.getProps(node)
|
if (!node.canResolve()) {
|
||||||
attributeSections[LayoutId] = InspectableObject(layoutProps.toMap())
|
val props = ComponentPropExtractor.getProps(node.component)
|
||||||
|
attributeSections[UserPropsId] = InspectableObject(props.toMap())
|
||||||
|
}
|
||||||
|
|
||||||
if (!node.canResolve()) {
|
attributeSections
|
||||||
val props = ComponentPropExtractor.getProps(node.component)
|
|
||||||
attributeSections[UserPropsId] = InspectableObject(props.toMap())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributeSections
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBounds(node: DebugComponent): Bounds =
|
override fun getBounds(node: DebugComponent): Bounds =
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ import com.facebook.flipper.plugins.uidebugger.model.SubtreeUpdateEvent
|
|||||||
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
||||||
import com.facebook.flipper.plugins.uidebugger.scheduler.Scheduler
|
import com.facebook.flipper.plugins.uidebugger.scheduler.Scheduler
|
||||||
import com.facebook.flipper.plugins.uidebugger.traversal.PartialLayoutTraversal
|
import com.facebook.flipper.plugins.uidebugger.traversal.PartialLayoutTraversal
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
data class ScanResult(
|
data class ScanResult(
|
||||||
val txId: Long,
|
val txId: Long,
|
||||||
val scanStart: Long,
|
val scanStart: Long,
|
||||||
val scanEnd: Long,
|
val scanEnd: Long,
|
||||||
val nodes: List<Node>
|
val nodes: List<MaybeDeferred<Node>>
|
||||||
)
|
)
|
||||||
|
|
||||||
const val observerType = "FullScan"
|
const val observerType = "FullScan"
|
||||||
@@ -62,6 +63,9 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun sendSubtreeUpdate(input: ScanResult) {
|
private fun sendSubtreeUpdate(input: ScanResult) {
|
||||||
|
val nodes = input.nodes.map { it.value() }
|
||||||
|
val deferredComputationComplete = System.currentTimeMillis()
|
||||||
|
|
||||||
val serialized =
|
val serialized =
|
||||||
Json.encodeToString(
|
Json.encodeToString(
|
||||||
SubtreeUpdateEvent.serializer(),
|
SubtreeUpdateEvent.serializer(),
|
||||||
@@ -69,7 +73,7 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
|||||||
input.txId,
|
input.txId,
|
||||||
observerType,
|
observerType,
|
||||||
ApplicationRefDescriptor.getId(context.applicationRef),
|
ApplicationRefDescriptor.getId(context.applicationRef),
|
||||||
input.nodes))
|
nodes))
|
||||||
val serializationEnd = System.currentTimeMillis()
|
val serializationEnd = System.currentTimeMillis()
|
||||||
|
|
||||||
context.connectionRef.connection?.send(
|
context.connectionRef.connection?.send(
|
||||||
@@ -89,6 +93,7 @@ class NativeScanScheduler(val context: Context) : Scheduler.Task<ScanResult> {
|
|||||||
input.scanStart,
|
input.scanStart,
|
||||||
input.scanEnd,
|
input.scanEnd,
|
||||||
input.scanEnd,
|
input.scanEnd,
|
||||||
|
deferredComputationComplete,
|
||||||
serializationEnd,
|
serializationEnd,
|
||||||
socketEnd,
|
socketEnd,
|
||||||
input.nodes.size)))
|
input.nodes.size)))
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import android.graphics.Bitmap
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.Immediate
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A chained descriptor is a special type of descriptor that models the inheritance hierarchy in
|
* A chained descriptor is a special type of descriptor that models the inheritance hierarchy in
|
||||||
@@ -81,7 +83,7 @@ abstract class ChainedDescriptor<T> : NodeDescriptor<T> {
|
|||||||
|
|
||||||
open fun onGetChildren(node: T): List<Any>? = null
|
open fun onGetChildren(node: T): List<Any>? = null
|
||||||
|
|
||||||
final override fun getData(node: T): Map<MetadataId, InspectableObject> {
|
final override fun getData(node: T): MaybeDeferred<Map<MetadataId, InspectableObject>> {
|
||||||
val builder = mutableMapOf<MetadataId, InspectableObject>()
|
val builder = mutableMapOf<MetadataId, InspectableObject>()
|
||||||
onGetData(node, builder)
|
onGetData(node, builder)
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@ abstract class ChainedDescriptor<T> : NodeDescriptor<T> {
|
|||||||
curDescriptor = curDescriptor.mSuper
|
curDescriptor = curDescriptor.mSuper
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder
|
return Immediate(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.graphics.Bitmap
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Descriptors are an extension point used during traversal to extract data out of arbitrary
|
Descriptors are an extension point used during traversal to extract data out of arbitrary
|
||||||
@@ -73,7 +74,7 @@ interface NodeDescriptor<T> {
|
|||||||
* Get the data to show for this node in the sidebar of the inspector. The object will be shown in
|
* Get the data to show for this node in the sidebar of the inspector. The object will be shown in
|
||||||
* order and with a header matching the given name.
|
* order and with a header matching the given name.
|
||||||
*/
|
*/
|
||||||
fun getData(node: T): Map<MetadataId, InspectableObject>
|
fun getData(node: T): MaybeDeferred<Map<MetadataId, InspectableObject>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of tags to describe this node in an abstract way for the UI Unfortunately this can't be an
|
* Set of tags to describe this node in an abstract way for the UI Unfortunately this can't be an
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.graphics.Bitmap
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.Immediate
|
||||||
|
|
||||||
object ObjectDescriptor : NodeDescriptor<Any> {
|
object ObjectDescriptor : NodeDescriptor<Any> {
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ object ObjectDescriptor : NodeDescriptor<Any> {
|
|||||||
|
|
||||||
override fun getChildren(node: Any) = listOf<Any>()
|
override fun getChildren(node: Any) = listOf<Any>()
|
||||||
|
|
||||||
override fun getData(node: Any) = mutableMapOf<MetadataId, InspectableObject>()
|
override fun getData(node: Any) = Immediate(mapOf<MetadataId, InspectableObject>())
|
||||||
|
|
||||||
override fun getBounds(node: Any): Bounds = Bounds(0, 0, 0, 0)
|
override fun getBounds(node: Any): Bounds = Bounds(0, 0, 0, 0)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import android.graphics.Bitmap
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
/** a drawable or view that is mounted, along with the correct descriptor */
|
/** a drawable or view that is mounted, along with the correct descriptor */
|
||||||
class OffsetChild(val child: Any, val descriptor: NodeDescriptor<Any>, val x: Int, val y: Int) {
|
class OffsetChild(val child: Any, val descriptor: NodeDescriptor<Any>, val x: Int, val y: Int) {
|
||||||
@@ -37,7 +38,7 @@ object OffsetChildDescriptor : NodeDescriptor<OffsetChild> {
|
|||||||
|
|
||||||
override fun getActiveChild(node: OffsetChild): Any? = node.descriptor.getActiveChild(node.child)
|
override fun getActiveChild(node: OffsetChild): Any? = node.descriptor.getActiveChild(node.child)
|
||||||
|
|
||||||
override fun getData(node: OffsetChild): Map<MetadataId, InspectableObject> =
|
override fun getData(node: OffsetChild): MaybeDeferred<Map<MetadataId, InspectableObject>> =
|
||||||
node.descriptor.getData(node.child)
|
node.descriptor.getData(node.child)
|
||||||
|
|
||||||
override fun getTags(node: OffsetChild): Set<String> = node.descriptor.getTags(node.child)
|
override fun getTags(node: OffsetChild): Set<String> = node.descriptor.getTags(node.child)
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ data class PerfStatsEvent(
|
|||||||
val traversalComplete: Long,
|
val traversalComplete: Long,
|
||||||
val snapshotComplete: Long,
|
val snapshotComplete: Long,
|
||||||
val queuingComplete: Long,
|
val queuingComplete: Long,
|
||||||
|
val deferredComputationComplete: Long,
|
||||||
val serializationComplete: Long,
|
val serializationComplete: Long,
|
||||||
val socketComplete: Long,
|
val socketComplete: Long,
|
||||||
val nodesCount: Int
|
val nodesCount: Int
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.facebook.flipper.plugins.uidebugger.model.MetadataUpdateEvent
|
|||||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
import com.facebook.flipper.plugins.uidebugger.model.PerfStatsEvent
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.SubtreeUpdateEvent
|
import com.facebook.flipper.plugins.uidebugger.model.SubtreeUpdateEvent
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@@ -37,7 +38,7 @@ data class CoordinateUpdate(val observerType: String, val nodeId: Id, val coordi
|
|||||||
data class SubtreeUpdate(
|
data class SubtreeUpdate(
|
||||||
val observerType: String,
|
val observerType: String,
|
||||||
val rootId: Id,
|
val rootId: Id,
|
||||||
val nodes: List<Node>,
|
val deferredNodes: List<MaybeDeferred<Node>>,
|
||||||
val startTime: Long,
|
val startTime: Long,
|
||||||
val traversalCompleteTime: Long,
|
val traversalCompleteTime: Long,
|
||||||
val snapshotComplete: Long,
|
val snapshotComplete: Long,
|
||||||
@@ -104,12 +105,13 @@ class TreeObserverManager(val context: Context) {
|
|||||||
sendMetadata()
|
sendMetadata()
|
||||||
|
|
||||||
val serialized: String?
|
val serialized: String?
|
||||||
|
val nodes = treeUpdate.deferredNodes.map { it.value() }
|
||||||
|
val deferredComptationComplete = System.currentTimeMillis()
|
||||||
if (treeUpdate.snapshot == null) {
|
if (treeUpdate.snapshot == null) {
|
||||||
serialized =
|
serialized =
|
||||||
Json.encodeToString(
|
Json.encodeToString(
|
||||||
SubtreeUpdateEvent.serializer(),
|
SubtreeUpdateEvent.serializer(),
|
||||||
SubtreeUpdateEvent(
|
SubtreeUpdateEvent(txId, treeUpdate.observerType, treeUpdate.rootId, nodes))
|
||||||
txId, treeUpdate.observerType, treeUpdate.rootId, treeUpdate.nodes))
|
|
||||||
} else {
|
} else {
|
||||||
val stream = ByteArrayOutputStream()
|
val stream = ByteArrayOutputStream()
|
||||||
val base64Stream = Base64OutputStream(stream, Base64.DEFAULT)
|
val base64Stream = Base64OutputStream(stream, Base64.DEFAULT)
|
||||||
@@ -118,8 +120,7 @@ class TreeObserverManager(val context: Context) {
|
|||||||
serialized =
|
serialized =
|
||||||
Json.encodeToString(
|
Json.encodeToString(
|
||||||
SubtreeUpdateEvent.serializer(),
|
SubtreeUpdateEvent.serializer(),
|
||||||
SubtreeUpdateEvent(
|
SubtreeUpdateEvent(txId, treeUpdate.observerType, treeUpdate.rootId, nodes, snapshot))
|
||||||
txId, treeUpdate.observerType, treeUpdate.rootId, treeUpdate.nodes, snapshot))
|
|
||||||
|
|
||||||
treeUpdate.snapshot.readyForReuse()
|
treeUpdate.snapshot.readyForReuse()
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,7 @@ class TreeObserverManager(val context: Context) {
|
|||||||
val socketEnd = System.currentTimeMillis()
|
val socketEnd = System.currentTimeMillis()
|
||||||
Log.i(
|
Log.i(
|
||||||
LogTag,
|
LogTag,
|
||||||
"Sent event for ${treeUpdate.observerType} root ID ${treeUpdate.rootId} nodes ${treeUpdate.nodes.size}")
|
"Sent event for ${treeUpdate.observerType} root ID ${treeUpdate.rootId} nodes ${nodes.size}")
|
||||||
|
|
||||||
val perfStats =
|
val perfStats =
|
||||||
PerfStatsEvent(
|
PerfStatsEvent(
|
||||||
@@ -140,9 +141,10 @@ class TreeObserverManager(val context: Context) {
|
|||||||
traversalComplete = treeUpdate.traversalCompleteTime,
|
traversalComplete = treeUpdate.traversalCompleteTime,
|
||||||
snapshotComplete = treeUpdate.snapshotComplete,
|
snapshotComplete = treeUpdate.snapshotComplete,
|
||||||
queuingComplete = onWorkerThread,
|
queuingComplete = onWorkerThread,
|
||||||
|
deferredComputationComplete = deferredComptationComplete,
|
||||||
serializationComplete = serializationEnd,
|
serializationComplete = serializationEnd,
|
||||||
socketComplete = socketEnd,
|
socketComplete = socketEnd,
|
||||||
nodesCount = treeUpdate.nodes.size)
|
nodesCount = nodes.size)
|
||||||
|
|
||||||
context.connectionRef.connection?.send(
|
context.connectionRef.connection?.send(
|
||||||
PerfStatsEvent.name, Json.encodeToString(PerfStatsEvent.serializer(), perfStats))
|
PerfStatsEvent.name, Json.encodeToString(PerfStatsEvent.serializer(), perfStats))
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import com.facebook.flipper.plugins.uidebugger.descriptors.Id
|
|||||||
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
||||||
import com.facebook.flipper.plugins.uidebugger.model.Node
|
import com.facebook.flipper.plugins.uidebugger.model.Node
|
||||||
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.Immediate
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will traverse the layout hierarchy until it sees a node that has an observer registered for
|
* This will traverse the layout hierarchy until it sees a node that has an observer registered for
|
||||||
@@ -29,9 +31,9 @@ class PartialLayoutTraversal(
|
|||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
internal fun NodeDescriptor<*>.asAny(): NodeDescriptor<Any> = this as NodeDescriptor<Any>
|
||||||
|
|
||||||
fun traverse(root: Any): Pair<List<Node>, List<Any>> {
|
fun traverse(root: Any): Pair<List<MaybeDeferred<Node>>, List<Any>> {
|
||||||
|
|
||||||
val visited = mutableListOf<Node>()
|
val visited = mutableListOf<MaybeDeferred<Node>>()
|
||||||
val observableRoots = mutableListOf<Any>()
|
val observableRoots = mutableListOf<Any>()
|
||||||
|
|
||||||
val stack = mutableListOf<Any>()
|
val stack = mutableListOf<Any>()
|
||||||
@@ -53,15 +55,16 @@ class PartialLayoutTraversal(
|
|||||||
|
|
||||||
if (shallow.contains(node)) {
|
if (shallow.contains(node)) {
|
||||||
visited.add(
|
visited.add(
|
||||||
Node(
|
Immediate(
|
||||||
descriptor.getId(node),
|
Node(
|
||||||
descriptor.getQualifiedName(node),
|
descriptor.getId(node),
|
||||||
descriptor.getName(node),
|
descriptor.getQualifiedName(node),
|
||||||
emptyMap(),
|
descriptor.getName(node),
|
||||||
descriptor.getBounds(node),
|
emptyMap(),
|
||||||
emptySet(),
|
descriptor.getBounds(node),
|
||||||
emptyList(),
|
emptySet(),
|
||||||
null))
|
emptyList(),
|
||||||
|
null)))
|
||||||
|
|
||||||
shallow.remove(node)
|
shallow.remove(node)
|
||||||
continue
|
continue
|
||||||
@@ -93,15 +96,17 @@ class PartialLayoutTraversal(
|
|||||||
val bounds = descriptor.getBounds(node)
|
val bounds = descriptor.getBounds(node)
|
||||||
val tags = descriptor.getTags(node)
|
val tags = descriptor.getTags(node)
|
||||||
visited.add(
|
visited.add(
|
||||||
Node(
|
attributes.map { attrs ->
|
||||||
descriptor.getId(node),
|
Node(
|
||||||
descriptor.getQualifiedName(node),
|
descriptor.getId(node),
|
||||||
descriptor.getName(node),
|
descriptor.getQualifiedName(node),
|
||||||
attributes,
|
descriptor.getName(node),
|
||||||
bounds,
|
attrs,
|
||||||
tags,
|
bounds,
|
||||||
childrenIds,
|
tags,
|
||||||
activeChildId))
|
childrenIds,
|
||||||
|
activeChildId)
|
||||||
|
})
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
|
Log.e(LogTag, "Error while processing node ${node.javaClass.name} $node", exception)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.uidebugger.util
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This abstracts over a value which could be available immediately or calculated later. The use
|
||||||
|
* case is for shifting computation to a background thread.
|
||||||
|
*/
|
||||||
|
abstract class MaybeDeferred<T> {
|
||||||
|
abstract fun value(): T
|
||||||
|
|
||||||
|
/** similar to map on an Option or Functor in a functional language. */
|
||||||
|
abstract fun <U> map(fn: (T) -> U): MaybeDeferred<U>
|
||||||
|
}
|
||||||
|
|
||||||
|
class Immediate<T>(private val value: T) : MaybeDeferred<T>() {
|
||||||
|
override fun value(): T = value
|
||||||
|
|
||||||
|
override fun <U> map(fn: (T) -> U): MaybeDeferred<U> = Immediate(fn(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
class Deferred<T>(private val lazyLoader: () -> T) : MaybeDeferred<T>() {
|
||||||
|
override fun value(): T = lazyLoader()
|
||||||
|
override fun <U> map(fn: (T) -> U): MaybeDeferred<U> {
|
||||||
|
return Deferred { fn(lazyLoader()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,11 +63,21 @@ const columns: DataTableColumn<PerfStatsEvent>[] = [
|
|||||||
return formatDiff(row.snapshotComplete, row.queuingComplete);
|
return formatDiff(row.snapshotComplete, row.queuingComplete);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'deferredComputationComplete',
|
||||||
|
title: 'Deferred processing time',
|
||||||
|
onRender: (row: PerfStatsEvent) => {
|
||||||
|
return formatDiff(row.queuingComplete, row.deferredComputationComplete);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'serializationComplete',
|
key: 'serializationComplete',
|
||||||
title: 'Serialization time',
|
title: 'Serialization time',
|
||||||
onRender: (row: PerfStatsEvent) => {
|
onRender: (row: PerfStatsEvent) => {
|
||||||
return formatDiff(row.queuingComplete, row.serializationComplete);
|
return formatDiff(
|
||||||
|
row.deferredComputationComplete,
|
||||||
|
row.serializationComplete,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ export type PerfStatsEvent = {
|
|||||||
start: number;
|
start: number;
|
||||||
traversalComplete: number;
|
traversalComplete: number;
|
||||||
snapshotComplete: number;
|
snapshotComplete: number;
|
||||||
serializationComplete: number;
|
|
||||||
queuingComplete: number;
|
queuingComplete: number;
|
||||||
|
deferredComputationComplete: number;
|
||||||
|
serializationComplete: number;
|
||||||
socketComplete: number;
|
socketComplete: number;
|
||||||
nodesCount: number;
|
nodesCount: number;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user