题
我的基准测试有问题吗?Immutable.js find()如何比array.find()慢8倍?
好吧,不完全公平,因为我在Immutable.List中使用Immutable.Map.但对我来说,这是一个现实世界的例子.如果我使用Immutable.js,那就是保护不变性并在某些方面获得性能(结构共享起作用).仅在对象的根处使用Immutable.js是没有意义的.
以下基准实际上来自另一个问题(我的也是).我对结果感到非常惊讶,我不得不单独发布以使其顺利进行.我在基准测试中做错了什么,或者性能差异真的很大吗?
背景
我的应用中的一些数据可以被视为应用元数据.原始数据位于服务器的数据库中.不会经常更新元数据.该应用程序将在启动时检查更新的元数据.
我到处都在使用Immutable.js,但我会回到简单的js来获取元数据.对于这种数据,不需要花哨的结构共享.
测试是按集合中的键查找值
收集10件物品
找到一百万次的价值
Mac mini核心i7 2.6
结果:
带有强制密钥的普通JS对象:8毫秒
使用find()的普通JS数组:127毫秒
Immutable.Map与数字键:185毫秒
使用find()的Immutable.List:972毫秒 !! 我很困惑
因为我正在使用React Native,如果我想达到60 fps,我总是要注意16 ms的限制.基准值似乎不是线性的.仅使用100次查找运行测试需要1 ms的Map和2 ms的List.那太贵了.
let Immutable = require('immutable');
let mapTest = Immutable.Map()
.set(1, Immutable.Map({value: 'one'}))
.set(2, Immutable.Map({value: 'two'}))
.set(3, Immutable.Map({value: 'three'}))
.set(4, Immutable.Map({value: 'four'}))
.set(5, Immutable.Map({value: 'five'}))
.set(6, Immutable.Map({value: 'six'}))
.set(7, Immutable.Map({value: 'seven'}))
.set(8, Immutable.Map({value: 'eight'}))
.set(9, Immutable.Map({value: 'nine'}))
.set(10, Immutable.Map({value: 'ten'}));
let listTest = Immutable.fromJS([
{key: 1, value: 'one'}, …Run Code Online (Sandbox Code Playgroud) 我主要喜欢React Native.从0.22开始一直使用它.目前在0.35.
但为什么链接本地图书馆就像彩票?我很少在第一次拍摄时使用它,而破坏的东西往往是完全不同的东西.
每次RN升级都是皮塔饼.这是我通常做的事情:
react-native upgrade (在每个问题上回答是以替换文件)react-native run-ios大多数时候,上述情况都不起作用.但是当我从XCode中编译应用程序时它确实有效.
从这里到工作的旅程run-ios往往是漫长而令人沮丧的.它涉及以下内容:
react-native unlink xyzrm -rf node_modulesyarn有时候上面的工作.大多数情况下它不起作用.通常,当我运行时,一些本机模块最终会出现在构建错误部分中react-native run-ios.从XCode运行照常工作.
最终出现在错误部分的本机模块每次都不一样.我还有一些"出货"的本机模块出现RN错误.(RCTGeolocation,RCTActionSheet,RCTWebSocket)
解决方案的下一个"级别"(当我无法得到上述内容时)工作是这样的:
react-native init nextAppAttemptyarn我已经在上面取得了一些成功,但是我将pita重命名为真实姓名并重新连接到我的GitHub仓库.
以下是我链接的本机模块:
react-native link react-native-fs && \
react-native link react-native-camera && \
react-native link react-native-code-push \
react-native link react-native-permissions && \
react-native link react-native-image-resizer && \
react-native link react-native-mixpanel && \
react-native link react-native-maps && …Run Code Online (Sandbox Code Playgroud) 我在React Native应用程序中使用Redutable使用Immutable.js.
元数据(例如查找表)从服务器获取,并作为Immutable.Map在应用程序中本地保存.查找值的键是整数(db中的主键).
当我获取数据时,所有整数键都被强制转换为字符串.这是js对象的正常行为.因此,当创建查找映射时,键将是字符串.
例:
let colors = Immutable.Map({
'10': 'yellow',
'20': 'pink',
..
})
Run Code Online (Sandbox Code Playgroud)
引用查找值的对象将引用存储为数字,如下所示:
let michael = Immutable.Map({
name: 'Michael',
colorId: 10
})
Run Code Online (Sandbox Code Playgroud)
由于Immutable.js不会将数字键强制转换为字符串,因此无法执行此操作:
let color = colors.get(michael.get('colorId'))
Run Code Online (Sandbox Code Playgroud)
以上内容与:
let color = colors.get(10)
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为id是一个字符串.这可行:
let color = colors.get('10')
Run Code Online (Sandbox Code Playgroud)
我通常使用Immutable.List来存储从服务器获取的数据集.要获得一个项目,我使用find().但是经常访问小的查找表(基本上是应用程序元数据)并且需要快速.
你是如何解决这个问题的?以下是一些需要考虑的选择:
let color = colors.get(michael.get('colorId') + '')
Run Code Online (Sandbox Code Playgroud)
缺点:
优点:
缺点:
优点:
缺点:
let colors = new Immutable.Map()
.set(10, 'yellow')
.set(20, 'pink')
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
来自简单性能测试的有趣数据. …
我的应用程序具有通过REST API提供的主题(颜色和样式).每当在服务器上更改主题时,应用程序都会通过套接字通信获得通知,因此它可以通过REST获取新主题.
主题是在Redux Saga中获取的,颜色被保存到Redux商店(以便能够持久保存到磁盘)以及我可以从任何地方到达的"全局"单例对象,即使是非连接组件.
当一个新主题到来时,我想重新渲染应用程序中的每个元素.我设法以一种hacky方式重新渲染所有连接商店的组件 - 通过注入一个虚拟属性,当新的主题被更改时,该属性会发生变化.
有没有办法forceUpdate整个应用程序?
问题领域:
哑组件(不知道主题变化)
非常聪明的组件(知道商店,但知道不会徒劳地重新渲染)
这是一个hacky force-re-render of react-navigation的例子:
myAppContainer.render() {
<AppRouter
screenProps={this.props.styling}
/>
}
Run Code Online (Sandbox Code Playgroud)
即我的AppContainer this.props.styling通过mapStateToProps.包装StackNavigator得到这个通过screenProps,当商店获得新的样式数据时,强制导航器重新渲染.
我不想继续这条hacky路径.相反,我想要一个forceUpdateEverything()我可以从我的电话中调用的功能AppContainer.有这样的事吗?
编辑以评论@bennygenel的答案:
我认为Benny所描述的基本上就是我所做的.this.props.styling中的更改会触发重新渲染.
但是我必须将这个实现到所有组件中并通过其screenProps"hack"反应导航,如我所述.这是我希望避免的,但我想我必须走很长的路.
我正在使用immutable.js,所以发送完整的样式而不仅仅是主题名称没什么大不了的,因为它只是一个指针,可以快速地与它的前值进行比较以寻找变化.
我没有让forceUpdate()工作,而不是调用它所调用的组件.我认为它不会通过所有孩子递归传播.
我正试图绕过Redux以及如何在React Native应用程序中实现它.
我得到了一般的想法,我喜欢它.但我不太确定如何构建我的商店.我将尝试用应用程序中的两个场景给出一个示例.
ProjectListScreen:使用ListView组件构建的项目列表.每行显示每个项目对象的大约5个字段.
ProjectScreen:显示特定项目的所有字段的ScrollView.项目对象可能非常大而且不完全平坦.例如,它包含一个指向图像的UUID数组.
那么,我应该有一个减速器来处理完整的"项目",还是应该有一个用于ProjectList的减速器和一个用于项目的减速器?即我应该考虑真实的域名或应用程序中的视图/屏幕?
我怀疑答案是模仿域名.但如果列表中有1000个项目怎么办?我需要将1000个项目加载到商店中,包括每个项目的所有字段.但我只需要其中五个字段来呈现ListView.由于用户无法在ProjectScreen中打开所有1000个项目,因此可能只会完全加载几个项目.一个项目的更改将强制while数组的副本,以保持不可变.
我不想陷入过早的优化,但我想从一开始就让商店的结构有点正确.我知道我可以使用Immutable.js来优化列表中项目的更新,但这会让我使用非JS对象,这感觉有点麻烦.
我宁愿使用无缝不可变,但我不认为SI的大型列表的这种部分更新会比复制列表更快.
我很想听到与UI渲染和其他任务相比,性能不会成为问题.这将使得与域结构一起使用变得简单.
我想用setNativeProps()一个<Surface>这样的:
render = () => (
<Surface
ref = {ref => this.surfaceRef = ref}
/>
)
moveSurface (x,y) => {
this.surfaceRef.setNativeProps({
transform: {[translateX: x}, {translateY: y}]
})
}
Run Code Online (Sandbox Code Playgroud)
由于任何ART组件似乎都未实现setNativeProps,因此此方法不起作用。我认为至少Surface可以实现此功能,因为它可以扩展Component。
背景:我成功完成了react-native-svg的操作(类似)。但是我需要更多的fps。ART比react-native-svg的性能要好一些,因此我想看看ART在setNativeProps上的表现如何,并将其与react-native-svg进行比较。
是否可以在 VSCode 中分配用于在主题之间切换的键盘快捷键?
我喜欢 Monokai 或 Monokai Seti 进行编码,但对于用 Markdown 编写文档,我认为轻主题提供了更好的可读性。我认为这是因为文档文本主要是一种颜色,而代码是为了可见性而突出显示的颜色。
对我来说最重要的是为 Markdown 预览提供一个轻量级的主题。如果 MD 预览窗格可以有一个浅色主题,而实际的 MD 代码是 Monokai 或其他任何东西,那就太好了。
我有一个 eventChannel 用于监听 webSockets,这工作正常。
我还想听一个动作USER_LOGGED_OUT并关闭频道。
END如果出现套接字错误或套接字关闭,我将通过发出信号来从通道内关闭通道,但如何根据外部操作执行此操作?
这是通道循环:
export function* websocketWatcher() {
const tokenResponse = yield take(RECEIVE_USER_TOKEN);
const accessToken = tokenResponse.payload.data.access_token;
const channel = yield call(createWebsocketChannel, accessToken);
try {
while (true) {
const action = yield take(channel);
yield put(action);
}
} finally {
console.log('Websocket channel terminated');
}
}
Run Code Online (Sandbox Code Playgroud)