【Flutter】Widget の == operator を override することが推奨されていない理由を深ぼりたい
元ドキュメントはこれ
Avoid overriding operator == on Widget objects. While it might seem like it would help by avoiding unnecessary rebuilds, in practice it hurts performance because it results in O(N²) behavior. The only exception to this rule is leaf widgets (widgets with no children), in the specific case where comparing the properties of the widget is likely to be significantly more efficient than rebuilding the widget and where the widget will rarely change configuration. Even in such cases, it is generally preferable to rely on caching the widgets, because even one override of operator == can result in across-the-board performance degradation as the compiler can no longer assume that the call is always static.
== operator
を上書きすることで、Element.updateChild の初めの分岐、child.widget == newWidget
を true にして、リビルドを伝播させないようにすると、そこには落とし穴(pitfalls)があるよって内容。
深掘りたい理由
-
== operator
の上書きが、なぜ O(N²) になるのかがわからない。- そもそも、どう上書きする前提なのかが明言されてない。いくつかのプロパティの比較に置き換えるってことなのかな?
== operator
の中身をプロパティの数だけやると、計算量が多くなっちゃうって話なのかな?
でも O(N^2) ではない気がする…
2020 年に、質問の Issue が上がってる(よく見たら Remi さんだった)
identical での比較の話になってるけど、Element 内で identical 比較してる実装は見つからない…
Widget のデフォルトの == operator
も identical じゃない。
わからん…
operator ==(Object other) => super == other;
bool
わかったかも
デフォルトの == operator
は、identical、つまり参照の比較になっていて、高速な計算が実現できる。
== operator
を上書きして、プロパティの比較にしてしまうと、プロパティが増えるたびに、== operator
計算量の最大値が増えていってしまう。
一応、Widget.==
に @nonVirtual
アノテーションが貼られた PR をペタリ
It was likely about non-leaf widgets.
If a widget has a child, and that child too overrides ==, then we could end up effectively comparing the entire widget tree.
But I don't see any issue with leaf widgets though.
https://github.com/flutter/flutter/issues/49490#issuecomment-578871743
ここが分からんのよなぁ…
child の == が override されていた場合、なんで全ての Widget を比較することになるの??
There are two things that can affect performance: the performance of the comparison itself, and the performance of the framework due to changes in comparison semantics. The former is probably relatively small. The latter can be much bigger depending on the app.
https://github.com/flutter/flutter/issues/49490#issuecomment-584415511
いや、そうなんよ
比較の計算量より、child.update(newWidget) の方がデカくねって話。
== operator
の運用は難しいから、下手なことはしないほうがいいってまとまってる感じする
ただ、ListView のアイテムの == operator
は面白いし、有効っぽいな
25ms から 16ms へのインパクトって書いてるし、60fps の最小フレームに影響してるから、採用の価値はかなり高い。