開発中のアプリでフリーズの問題を追跡しようとしています。私はNSAutoreleasePoolの深いところにいるかもしれないし、物事をねじっています。NSAutoreleasePoolを使用してフリーズする
アプリはmidiファイルを再生しています。 NSAutoreleasePoolを使用する「simRespondToFileNote」コードをコメントアウトすると、フリーズしません。私はコードを実行させると、それは一見無作為なポイントでフリーズします。クラッシュログ/コンソール出力は、問題の発生場所を示さないようです。ここで
は、プログラムの流れです:
私は低音ミディLIB(C libに)を使用しています。それは独自のスレッドでMIDIファイルを再生します。
midiイベントが発生すると、コールバックがトリガされ、NSDictionaryでMIDIイベントデータをラップし、メインスレッドにルーティングして、UIの更新やその他の処理を実行できます。メッセージはPARAMとしてNSDictionaryのインスタンスを使用して別のオブジェクトに送られるデリゲートから
- (void)forwardFileNoteIn:(int) note withVelocity: (int) velocity { int position = BASS_ChannelGetPosition(midiFileStream, BASS_POS_MIDI_TICK); float percent = ((float)position/(float)totalTicks); int ticksInLoop = outLoopTick - inLoopTick; QWORD bytes=BASS_ChannelGetPosition(midiFileStream, BASS_POS_BYTE); // get position in bytes double seconds=BASS_ChannelBytes2Seconds(midiFileStream, bytes); // translate to seconds int timeStamp =seconds*1000; // translate to milliseconds NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys: @"fileNoteIn", @"eventType", [NSNumber numberWithInt:note], @"note", [NSNumber numberWithInt:velocity],@"velocity", [NSNumber numberWithInt:timeStamp],@"timeStamp", [NSNumber numberWithInt:position],@"position", [NSNumber numberWithFloat:percent],@"percentPlayed", [NSNumber numberWithInt:ticksInLoop],@"ticksInLoop", nil]; [delegate performSelectorOnMainThread:@selector(midiFileEvent:) withObject:midiData waitUntilDone:NO]; [pool release];
}
- :ここ
ルーティングを行うコードです。そのオブジェクトは、すぐに別のオブジェクトにNSDictionaryインスタンスを送信するか、または短い遅延の後に送信するようにキューに入れます(performSelector:afterDelay:を使用)。
キューに入れられたメッセージがトリガーされる前にNSAutoreleasePoolがNSDictionaryインスタンスを削除している可能性はありますか?私はプールをどこにでも排水していません - 私はそれをしなければいけませんか?
- (void)simRespondToFileNote:(NSDictionary *)dictionary
{
int velocity = [[dictionary objectForKey:@"velocity"] intValue];
if (velocity == 0){
// noteOff - send it through
[delegate routeUserSimMidiEvent:dictionary];
} else {
float totalPercentCorrect = [dataSource getUserCorrectPercent];
int note = [[dictionary objectForKey:@"note"] intValue];
if (totalPercentCorrect < _userAccuracy){
float lateNoteOnTimeDelay = (dataSource.postTimeHighAccuracy - (dataSource.postTimeHighAccuracy /4))/1000.;
float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create noteOff data w/ velocity == 0; timeStamp == 0;
NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:note], @"note",
[NSNumber numberWithInt:0],@"velocity",
[NSNumber numberWithUnsignedInt:0],@"timeStamp",
nil];
[self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay];
[self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay];
[pool release];
} else {
float lateNoteOnTimeDelay = (dataSource.postTimeLowAccuracy + (dataSource.postTimeLowAccuracy /4))/1000.0;
float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create noteOff data w/ velocity == 0; timeStamp == 0;
NSDictionary *midiData =[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:note], @"note",
[NSNumber numberWithInt:0],@"velocity",
nil];
// queue late noteOn
[self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay];
// queue late noteOff
[self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay];
[pool release];
}
}
}
私は 'simRespondToFileNote:'でautoreleaseプールを取り出し、それがどのように冗長であるかを理解しています。まだ凍っている。私は(正しい用語をここでは知らない)原因が大きすぎるスタック(?)を元の辞書( 'forwardFileNoteIn:'から)を再利用することによって、複数のメソッド呼び出しを介してargとして渡します。 –
辞書を渡すのは非常に安いです。 ObjCはヒープ上のすべてのオブジェクトを割り当て、ポインタのみを渡します。だから、それは辞書の通過ではありません。私はInstrumentsを介してこれを実行し、ハングアップ中にCPUに何がぶつかっているのかを確認します。ありがとう。 –
ありがとう。辞書は、高価なアプローチではないことを喜んで行きました。特定の辞書がどれくらいのメモリを使用しているかを判断する方法はありますか?辞書のオーバーヘッド?インストゥルメント、メモリ、割り当て、ゾンビなどでプロジェクトを実行しました。問題と思われるリークや問題は表示されません(問題を構成するものがわからない可能性があります); –