Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2010-02-23

AppSalesの最新版がものすごく機能Upしている件 00:18  AppSalesの最新版がものすごく機能Upしている件 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  AppSalesの最新版がものすごく機能Upしている件 - Ni chicha, ni limona - 平均から抜けられない僕  AppSalesの最新版がものすごく機能Upしている件 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

iPhoneアプリ開発グループの記事で、id:ktakayamaさんが「 AppSales に累計の表示をつけた - iOS プログラミングメモ - iPhoneアプリ開発グループ」というタイトルで、AppSalesなる開発者向けアプリにTotal(売上合計)機能を追加されました。


このアプリは非常に便利で、これさえ持っていればいちいちブラウザiTunes Connectに接続する必要もなく売上をダウンロードできますし、さらには日毎、週毎の売上を集計してくれるスグレモノです。

私も同氏が公開されたのを機会に今までずっと重宝してきました。

ところが問題発生

困ったことがおきました。

今月18日前後でアクセスする際のURLApple側で変更されたらしく、その影響でデータが同アプリではダウンロードできなくなってしまったのです。


「さて、困ったな」と思って色々と見ていたところ、ちょうど良いタイミングで、最初の開発者であるOrtwin Gentz氏のリポジトリ当該問題の修正ソースがコミットされていました。

そこでさっそく

% git pull git://github.com/omz/AppSales-Mobile.git master

として変更を取り込んで、新しい版でも同アプリを継続して使うことができるようになりました。ラッキー。めでたしめでたし。


ところが話は続きまして、

上記でマージした版を作成した2日後、Jon Keanと名乗る方から


 「君のリポジトリにボクのリポジトリをPullしてみないか。そりゃもう色んな改善があるからね、すごいよ*1


というPull Requestが届きました。

何だ何だ?と恐る恐る調べてみると、それはすごいコミットの数。主立った改善点だけでも列挙すると、

などなど。

メンテナが彼に代わったのかよく分かりませんが、かなりの機能追加や改善が頻繁に行われていました。

もちろん、実際に動作させてみた感触も良い感じ。


というわけで再び

% git pull git://github.com/jonkean/AppSales-Mobile.git master

として取り込んで、自分のリポジトリにPushしておきました。

URLを以下に記しますので、興味のある方はぜひご利用くださいませ。


 no title


 (Jon Kean氏のリポジトリこちら。頻繁にアップデートされているようですので、最新の最新版はこちらを追うと良いかもです)


・・・ちなみに今回の問題はというと、自分のやったことは未だマージ作業だけであるという点。すみません頑張ります。

*1:すみません、意訳です。

2010-02-15

[iPhone][thread] iPhoneでのスタックサイズ 18:42  [iPhone][thread] iPhoneでのスタックサイズ - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][thread] iPhoneでのスタックサイズ - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][thread] iPhoneでのスタックサイズ - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

先にオチを書いておきます。今回確認したことは、Appleの公開しているドキュメント「Threading Programming Guide」にバッチリ書いてあることでした。

コメントでご指摘いただいたRNatoriさん、ありがとうございました。

何ともお恥ずかしい限りです。

それともう1つ。スタックサイズはどうやっても変更できないみたいです。POSIXAPIを使うと成功が返ってくるもののサイズは変わらず、コンパイルスイッチで上限を設けても変化無し。

残念ですが、そういうモノみたいです。

組込開発を職業にしているとリソースの上限がとても気になります。

たとえばメモリをどこまで使っていいのか、何秒以内に処理を終わらせなければならないのかなどなど。限界を知っておかないと落ち着いて作業も出来ず夜も眠れないほどです。*1


というわけで、「iPhone OSで、1スレッドが確保するスタックのサイズ」を計測してみることにしました。

試した環境はiPhone 3GS(16GB)、OSSDKも含めて3.1.3です。

計測に使用したコード

#include "pthread.h"

void *threadFunc(void *arg) {
	// スタックサイズ計測
	void*  stack_base = pthread_get_stackaddr_np(pthread_self());
	size_t stack_size = pthread_get_stacksize_np(pthread_self());
	NSLog(@"Thread: base:%p / size:%u", stack_base, stack_size);
	return NULL;
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {    
	// スタックサイズ計測
	void*  stack_base = pthread_get_stackaddr_np(pthread_self());
	size_t stack_size = pthread_get_stacksize_np(pthread_self());
	struct rlimit limit;
	getrlimit(RLIMIT_STACK, &limit);
	NSLog(@"Main thread: base:%p / size:%u", stack_base, stack_size);
	NSLog(@"  rlimit-> soft:%llu / hard:%llu", limit.rlim_cur, limit.rlim_max);
	
	// スレッド作成
	pthread_t thread;
	pthread_create(&thread, NULL, threadFunc, NULL);
	
    // Override point for customization after app launch    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

上記ソースをシミュレータと実機上で動かして、その結果を調べました。

結果

まずログの出力を載せます。

シミュレータ

Main thread: base:0xc0000000 / size:524288

rlimit-> soft:8388608 / hard:67104768

Thread: base:0xb014b000 / size:524288


実機

Main thread: base:0x30000000 / size:524288

rlimit-> soft:1044480 / hard:1044480

Thread: base:0xf1000 / size:524288

これだと分かりにくいので、単位をhuman readableにして表にまとめます。

-メインスレッド(普通の)スレッド
シミュレータ8MBytes512KBytes
実機1MBytes512KBytes

※ここでメインスレッドの情報にgetrlimit(2)を採用している理由は参考サイト1の「2. スタック領域情報の取得」をご覧ください。

何とシミュレータと実機とでメインスレッドスタックサイズが異なるという結果が出ました。そして、スレッド1つ作るたびにメモリを最低512KBを消費していることも分かりました。


後者はiPod 1GやiPhone 3Gをターゲットにしている場合、なおかつカメラアプリなどのメモリを大量に消費するアプリを作っている場合には影響が大きいかもしれません。


まとめ

  • メインスレッド(普段の処理で使用するスレッドです)のスタックサイズはシミュレータと実機とで異なることが分かりました。
    • 再帰を駆使したプログラムを書いていて、実機とで挙動が異なる場合は注意が必要です
  • スレッドを何個も作る場合にはメモリ消費に注意が必要なことが分かりました。
  • ・・・気になってしょうがないならどうして今まで調べなかった、という反省をしなければいけません。

参考サイト

今回の調査にて参考にしたサイトです。

スレッドを扱うなら、どちらも一度は目を通しておくべきサイトです。

  1. スタックオーバーフローのハンドリング (Stack Overflow Handling)
  2. Threadのスタック - memologue

*1:半分冗談ですが、半分は本当です。

RNatoriRNatori2010/02/15 19:12Threading Programming GuideのThread Costsという項目にもスタックサイズについて書いてありますね。http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/10000057i-CH15-SW2

paellapaella2010/02/15 21:38ありがとうございます!まさしく書いてありますね…。技術者にとって一番大切なこと「仕様書はちゃんと読む」が実践出来ていなくて恥ずかしい限りです。

MaxPowermepMaxPowermep2018/12/29 10:52Download missing dll from <a href=http://founddll.com/ntdll-dll/>Error ntdll.dll</a> page. Fix the error now!

EJblirmEJblirm2018/12/31 15:00Elton John is my favourite piano musician of the world. I’m glad to present for you this tour list 2019. Check <a href=http://eltonjohntour2019.com>Elton John retirement tour</a> link to get your best ticket for the last Elton John tour in 2019.

CliffmepCliffmep2019/01/08 08:16Joe Bonamassa is a famous country singer, so don't miss the possibility to visit <a href=http://joebonamassatour.com/>Joe Bonamassa tour </a>

epirexupiepirexupi2019/04/15 02:17http://theprettyguineapig.com/amoxicillin/ - Buy Amoxicillin <a href="http://theprettyguineapig.com/amoxicillin/">Amoxicillin 500 Mg</a> hev.mtpp.iphone-dev.g.hatena.ne.jp.gui.jv http://theprettyguineapig.com/amoxicillin/

ajobudusajobudus2019/04/15 02:49http://theprettyguineapig.com/amoxicillin/ - Generic Amoxicillin 500 Mg <a href="http://theprettyguineapig.com/amoxicillin/">Amoxicillin 500mg Capsules</a> sfb.asjm.iphone-dev.g.hatena.ne.jp.mzj.dl http://theprettyguineapig.com/amoxicillin/

2010-02-03

[NSFileManager] フォルダ内ファイルの合計サイズを調べる 18:42  [NSFileManager] フォルダ内ファイルの合計サイズを調べる - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [NSFileManager] フォルダ内ファイルの合計サイズを調べる - Ni chicha, ni limona - 平均から抜けられない僕  [NSFileManager] フォルダ内ファイルの合計サイズを調べる - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

フォルダに含まれているファイルの合計サイズをCocoa touchで調べる方法が分かりましたので、以下にメモを残しておきます。

- (unsigned long long int)folderSize:(NSString *)folderPath {
    NSArray *filesArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:folderPath error:nil];
    NSEnumerator *filesEnumerator = [filesArray objectEnumerator];
    NSString *fileName;
    unsigned long long int fileSize = 0;
    
    while (fileName = [filesEnumerator nextObject]) {
         NSDictionary *fileDictionary = [[NSFileManager defaultManager]
                                        attributesOfItemAtPath:[folderPath stringByAppendingPathComponent:fileName]
                                        error:nil];
        fileSize += [fileDictionary fileSize];
    }
    
    return fileSize;
}

これまでの定番だった -fileAttributesAtPath:traverseLink: は iPhone SDK 3.1 からdeprecatedになっているので要注意です。*1

上記のメソッドで、たとえばSandbox内のDocumentsフォルダで調べる場合は、


	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	NSLog(@"total file size: %llu", [self folderSize:[paths objectAtIndex:0]]);

みたいに使います。


これの活用例として、「このフォルダの最大サイズを何MBまでに制限したい」「Free版では保存できる容量を(以下同じ)」などが考えられますね。


注意

この処理ではディレクトリ内を再帰的に調べていません(そのはず)。ディレクトリ内をトラバースしたい場合には、上記ソースから一手間加えることが必要です。*2


多謝

Sandbox内のDocumentsフォルダへのパスを調べる方法については、Bugle Diaryのこちらの記事(リンク)を参考にしました。

ありがとうございます。

*1:attributesOfItemAtPath:error:自体は2.0から用意されています。

*2:調べ切れていないので、どなたかコメントしていただけると嬉しいです。