小编Mic*_*ael的帖子

性能:Immutable.js Map vs List vs plain JS

我的基准测试有问题吗?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)

javascript immutable.js

28
推荐指数
2
解决办法
6922
查看次数

为什么"反应本地链接某些原生模块"是彩票?

我主要喜欢React Native.从0.22开始一直使用它.目前在0.35.

但为什么链接本地图书馆就像彩票?我很少在第一次拍摄时使用它,而破坏的东西往往是完全不同的东西.

每次RN升级都是皮塔饼.这是我通常做的事情:

  1. npm i react-native@0.35
  2. react-native upgrade (在每个问题上回答是以替换文件)
  3. 在info.plist中插入我的东西(它被替换了..)
  4. 重新安装pods
  5. 重新链接所有本机模块
  6. 屏住呼吸试试 react-native run-ios

大多数时候,上述情况都不起作用.但是当我从XCode中编译应用程序时它确实有效.

从这里到工作的旅程run-ios往往是漫长而令人沮丧的.它涉及以下内容:

  1. 取消链接所有本机模块 react-native unlink xyz
  2. 手动删除unlink未删除的标头搜索路径
  3. rm -rf node_modules
  4. yarn
  5. 产品/从XCode内清理
  6. 安装pods
  7. 链接本机模块

有时候上面的工作.大多数情况下它不起作用.通常,当我运行时,一些本机模块最终会出现在构建错误部分中react-native run-ios.从XCode运行照常工作.

最终出现在错误部分的本机模块每次都不一样.我还有一些"出货"的本机模块出现RN错误.(RCTGeolocation,RCTActionSheet,RCTWebSocket)

解决方案的下一个"级别"(当我无法得到上述内容时)工作是这样的:

  1. react-native init nextAppAttempt
  2. 将代码,资产,.babelrc等复制到新文件夹
  3. yarn
  4. 链接所有模块
  5. 安装pods

我已经在上面取得了一些成功,但是我将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

11
推荐指数
1
解决办法
1214
查看次数

Immutable.js使用数字键映射(包括性能测试)

我在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().但是经常访问小的查找表(基本上是应用程序元数据)并且需要快速.

你是如何解决这个问题的?以下是一些需要考虑的选择:

1.搜索时手动将键转换为字符串

let color = colors.get(michael.get('colorId') + '') 
Run Code Online (Sandbox Code Playgroud)

缺点:

  • 不是一个有吸引力的解 似乎错误修剪给我.

2.将普通js对象用于查找列表

优点:

  • 对象键查找在js中很快
  • 自动强制键到字符串,两种方式(写和读)

缺点:

  • 理想情况下,我想在任何地方使用Immutable.js.

3.将List.find()用于查找表

优点:

  • 与大数据集的概念相同

缺点:

  • 我不知道使用List.find()而不是Map.get()对性能的影响

4.仔细制作Immutable.Map以使用数字键

let colors = new Immutable.Map()
  .set(10, 'yellow')
  .set(20, 'pink')
Run Code Online (Sandbox Code Playgroud)

优点:

  • 地图中的键将匹配引用键的值(即两者都是数字)

缺点:

  • 笨重
  • 键已经被强制转换为通过线路发送的json对象中的字符串,所以我基本上将它们转换回数字(我认为)

编辑..做了一些性能测试

来自简单性能测试的有趣数据. …

javascript immutable.js

6
推荐指数
0
解决办法
577
查看次数

如何在React Native中重新渲染所有内容

我的应用程序具有通过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()工作,而不是调用它所调用的组件.我认为它不会通过所有孩子递归传播.

reactjs react-native redux

6
推荐指数
1
解决办法
4968
查看次数

我应该在域之后还是在应用程序查看之后构建Redux存储?

我正试图绕过Redux以及如何在React Native应用程序中实现它.

我得到了一般的想法,我喜欢它.但我不太确定如何构建我的商店.我将尝试用应用程序中的两个场景给出一个示例.

ProjectListScreen:使用ListView组件构建的项目列表.每行显示每个项目对象的大约5个字段.

ProjectScreen:显示特定项目的所有字段的ScrollView.项目对象可能非常大而且不完全平坦.例如,它包含一个指向图像的UUID数组.

那么,我应该有一个减速器来处理完整的"项目",还是应该有一个用于ProjectList的减速器和一个用于项目的减速器?即我应该考虑真实的域名或应用程序中的视图/屏幕?

我怀疑答案是模仿域名.但如果列表中有1000个项目怎么办?我需要将1000个项目加载到商店中,包括每个项目的所有字段.但我只需要其中五个字段来呈现ListView.由于用户无法在ProjectScreen中打开所有1000个项目,因此可能只会完全加载几个项目.一个项目的更改将强制while数组的副本,以保持不可变.

我不想陷入过早的优化,但我想从一开始就让商店的结构有点正确.我知道我可以使用Immutable.js来优化列表中项目的更新,但这会让我使用非JS对象,这感觉有点麻烦.

我宁愿使用无缝不可变,但我不认为SI的大型列表的这种部分更新会比复制列表更快.

我很想听到与UI渲染和其他任务相比,性能不会成为问题.这将使得与域结构一起使用变得简单.

javascript immutable.js react-native redux

5
推荐指数
1
解决办法
859
查看次数

如何在本机ART对象上使用setNativeProps()?

我想用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进行比较。

graphics react-native

5
推荐指数
0
解决办法
140
查看次数

使用键盘快捷键切换主题

是否可以在 VSCode 中分配用于在主题之间切换的键盘快捷键?

我喜欢 Monokai 或 Monokai Seti 进行编码,但对于用 Markdown 编写文档,我认为轻主题提供了更好的可读性。我认为这是因为文档文本主要是一种颜色,而代码是为了可见性而突出显示的颜色。

对我来说最重要的是为 Markdown 预览提供一个轻量级的主题。如果 MD 预览窗格可以有一个浅色主题,而实际的 MD 代码是 Monokai 或其他任何东西,那就太好了。

visual-studio-code

4
推荐指数
2
解决办法
3759
查看次数

当某个动作发生时如何关闭 eventChannel

我有一个 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)

react-native redux-saga

2
推荐指数
1
解决办法
1104
查看次数