質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

2回答

1562閲覧

SwiftのFor文について

退会済みユーザー

退会済みユーザー

総合スコア0

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2016/03/23 01:58

OSX10.11.4, Xcode7.3, Swift2.2です。
個人的にアプリ開発を始めようと思ったのですが、For文内でメモリが増えてしまい、
思うようにできず困っています。

例えばですが、Xcodeを開き、「File」, 「New」, 「Project」,
「OSX-Application」, 「Cocoa Application」で新規にプロジェクトを作成し
「AppDelegate」に下記のコードを書いたとします。
追加した構文では class T のインスタンスを生成しているだけで
画面表示直後のメモリ使用量には影響無いと思っていました。

ですが実際は、追加構文あり: 9MB, なし: 27.3MB と変化しました。
インスタンスが本当に解放されているか確かめようと class T に deinit文を追加し
print 文で表示してみましたが、全てのインスタンスが解放されていました。

for文の入れ子でクラスのインスタンスを作り
配列に入れると同じ現象が起きてしまいますが、この場合原因は何でしょうか?

Swift

1import Cocoa 2 3@NSApplicationMain 4class AppDelegate: NSObject, NSApplicationDelegate { 5 6 func applicationDidFinishLaunching(aNotification: NSNotification) { 7 8 // 追加 9 for _ in 0..<1 { 10 let max = 1000000 11 var a: [T] = [] 12 for _ in 1...max { 13 a += [T()] 14 } 15 } 16 17 } 18} 19 20// 追加 21class T {}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ですが実際は、追加構文あり: 9MB, なし: 27.3MB と変化しました。

追加構文ありの方が 小さく 書かれていますが、これは書き間違いでしょうか?

追加構文ありの方が 大きい という前提で、質問の内容は、大量のインスタンスの生成でメモリの使用量が増え、それらのインスタンスを削除した後も元に戻らないのがなぜですか? ということだと理解しました。

これは正常な動作です。Swift を含め、ほとんどの言語の実行環境は、オブジェクトを格納するためにヒープ領域という、ある程度まとまった大きさのメモリ領域を確保します。ヒープ領域の初期サイズはあまり大きくありませんが、オブジェクトを格納しきれなくなりそうになると、そのサイズが拡張されます。

いったん拡張したヒープは、オブジェクトを解放して空きができた後も、簡単には元のサイズに縮小されません。これは、以下のような理由によるものです。

  1. ヒープ領域に、まだ生きているオブジェクトがまばらに残っており、まとまった領域を解放することができない。オブジェクトを移動して、ヒープ領域の一箇所にまとめる方法もあるが、これには実行コストがかかる。また、Swift がこのような方法を採用しているかは不明。(ガベージコレクションを採用している言語では、オブジェクトの移動をすることが多いが、Swift はリファレンスカウントという、別の方法を採用している)

  2. ヒープ領域の確保には、OSカーネルとのやりとりが発生するため、ある程度の実行コストがかかる。ヒープ領域をすぐに解放しないで、この後、生成されるオブジェクトのために再利用した方が、実行速度の面で有利。

投稿2016/03/23 14:51

tatsuya6502

総合スコア2035

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/25 22:33

丁寧なご回答ありがとうございます。 お礼が遅れてしまい申し訳ありません。 しかも指摘して頂いた通り文面が間違っていましたね・・・。 これもありがとうございます。 実行環境の動作など勉強になりました。 しかしこような動きをするのなら 一時的にでもメモリを一定以上消費するようなコードは 書いてはダメということですね。 元々私がやりたかった事はMySQLの読込み(SELECT)で、 メモリを大量に使用しないようにLIMITとFor文で少しずつ回したのですが、 メモリが解放されないので今回の質問をさせて頂きました。 もう少し粘って工夫してみます。 ありがとうございました。
guest

0

ガベージコレクションのためではないでしょうか。
そもそも、そのような大量のデータを扱う場合、オンメモリでは無理があるので、他の方法を検討する方がよろしいかと思われます。

投稿2016/03/23 02:14

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/03/25 22:23

ご回答ありがとうございます。お礼が遅れてしまい申し訳ありません。 ただSwift はガベージコレクションではないようです。 MySQLの読込み(SELECT)を、 メモリを大量に使用しないようにLIMITとFor文で少しずつ回したのですが、 メモリが解放されないので今回の質問をさせて頂きました。 他の方法を考えてみます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問