2017-12-12 9 views
0

私は高階関数でコードを書いて、私はそうような時の表現を一の変換を書き出すために多くのクリーナーであることがわかりました。不要な大きな変数を削除するswiftcコンパイラの最適化はありますか?

let children = objects.map { $0.children } 
let validChildren = children.filter { $0.isValid } 
let sortedChildren = validChildren.sorted { $0.count < $1.count } 

しかし、私はこれらの各知っています関数は変数に格納している新しいArrayオブジェクトを返します。理論的には、毎回新しいArrayを作成して保持し、多くのメモリを浪費しています。不要な配列が使用後に破棄されるように、呼び出しを1行として記述する方がよいでしょう。

let sortedChildren = objects.map { $0.children } .filter { $0.isValid } .sorted { $0.count < $1.count } 

これは、コードの1行で非常に多くのことが起こっているので、後で読むのが面倒です。だから私の質問です:Swiftのコンパイラは、コンパイル時に私の欲求を赦し、未使用の変数を削除する最適化を持っていますか?

+0

*「1行のコードには非常に多くのことがあります」* - '.filter'の前と' .sorted'の前に改行することができることに注意してください。 –

+1

これは時期尚早の最適化のような臭いです。 – rmaddy

+1

コンパイラはあなたを別の変数に分割することを心配していません。しかし、あなたが@MartinRが言ったようにメモリを心配すれば、改行を使用するか、少なくともあなたの変数をprivate/fileprivateまたはlazyとして宣言することができます。 – Vollan

答えて

1

これは@MartinRによって質問のコメントで言及されましたが、正式な回答と情報源に値しました。

As per the Swift repository docs:

スイフトのすべての標準ライブラリコンテナは、COW を使用する値の種類(コピーオンライト)[4]の代わりに、明示的なコピーのコピーを実行するためです。 では、多くの場合、深いコピーを実行する代わりに、コンテナを保持することによって不要なコピーをコンパイラが削除することができます。これは、コンテナの参照カウント が1より大きく、コンテナが変更されている場合にのみ、基礎となるコンテナをコピーすることによって行われる です。以下では 例えばdは Cに割り当てられている場合、何のコピーは発生しないが、D 2を付加することによって、構造変異を受けたときに、dが がコピーされ、その後2は、Dに追加されます:

var c: [Int] = [ ... ] 
var d = c  // No copy will occur here. 
d.append(2)  // A copy *does* occur here. 

高次関数は、呼び出されたオブジェクトを変更しないため、結果がサイズに最適化されているという確信をもって言えるでしょう。

1

2つのバージョンに違いはありません。

結果を変数に代入しなくても、関数呼び出しの結果を格納するためにリストの1つの新しいインスタンスが作成されます。したがって、メモリ使用量は同じです。

objects.map { $0.children }.filter { $0.isValid }.sorted { $0.count < $1.count } 

だから、各関数呼び出しの後、我々はまだ関係なく、その関数の結果を格納しないようにメモリを必要とします assign、それを変数にするかどう。別の変数への assigningはオブジェクトのコピーを作成しません。

関連する問題