2012年6月30日土曜日

since_idの決め方

相変わらず仕事がつまってて全然いじれてないけど、今日は出張でいつもよりは早く帰れたからsince_idでの永久掘削続き。たまに(場合によってはしょっちゅう)loadingにすげー時間がかかることがあり、最初はネットワークの調子が悪いのかapiのサーバがヘタってるのかなどと考えていたが、いろいろ検証してみるとどうやらsince_idの確定アルゴリズムで遅延が起こってる様子。なーんだ自分のせいか安心した。

since_idを確定できるのは、lastidがおかわりしたJSONの中に含まれ、且つlastidとJSONの最後のidが等しくない場合なので、それ以外のケースでは、
1.lastidよりおかわりしたJSONの最初のidが小さい場合
2.lastidよりおかわりしたJSONの最後のidが大きい場合
に切り分けて、1の場合はlastidとJSONの最初のidの差分をsince_idに+=し、2の場合は逆に-=して再度おかわりして確定できるまで繰り返していた。さらに1の場合だと+=した際にsince_idがlastidを超えるという馬鹿なケースが起こるので、その場合は前述のとおりid乖離平均にlimit+1をかけた数値を半分(それでも多ければ戻ってくるたびに3分の1、4分の1〜)していた(これを3とする)。

上記アルゴリズムで、たまに(場合によってはしょっちゅう)以下の2パターンの遅延が発生していた。
A.1を数十回繰り返してもなかなかJSONの最初のidがlastidを超えない
B.1と2を行ったり来たり、または1と3を行ったり来たりする
Aについては、まあ待ってれば確定するが、それでも分単位でloadingが終わらないのは精神衛生上よくないしサーバにも優しくない。Bはさらに致命的で、ほぼ無限ループに近い状態になる。
Aは+=する値を倍々してスピードを上げ、Bは行き過ぎた分戻すだけなのでスピードを下げておかわりする。コードは以下のとおり。
- (void)apiTicket:(OAServiceTicket *)ticket didFinishWithData:(NSData *)data{
 loadflg=NO;
 NSDictionary *bd=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
 long long topid=[[[bd valueForKeyPath:@"response.posts.id"]objectAtIndex:0]longLongValue];
 int skip=0;
 if(offset+limit>250){
  if(lastid>topid){
   if(adjflg==1){adj2=2;since_id+=(lastid-topid)*adj1++;}
   else if(adjflg==2){adj1=2;since_id+=(lastid-topid)/adj2++;}
   else since_id+=lastid-topid;
   adjflg=1;
   if(since_id>=lastid){adj1=2;adj2=2;since_id=lastid-(([[idArr objectAtIndex:0]longLongValue]-[[idArr lastObject]longLongValue])/([idArr count]-1)*(limit+1))/adj3++;}
   offsinceval=[NSString stringWithFormat:@"%lld",since_id];[self reqJSON];
   return;
  }else if(lastid<=[[[bd valueForKeyPath:@"response.posts.id"]lastObject]longLongValue]){
   if(adjflg==2){adj2=2;since_id-=(topid-lastid)*adj1++;}
   else if(adjflg==1){adj1=2;since_id-=(topid-lastid)/adj2++;}
   else since_id-=topid-lastid;
   adjflg=2;
   offsinceval=[NSString stringWithFormat:@"%lld",since_id];[self reqJSON];
   return;
  }else{
   adjflg=0,adj1=2,adj2=2,adj3=2;
   for(id idnum in [bd valueForKeyPath:@"response.posts.id"]){
    if(lastid<=[idnum longLongValue]) skip++;
    else break;
   }
  }
 }else if(lastid!=0&&lastid<=topid){
  offset++;offsinceval=[NSString stringWithFormat:@"%d",offset];[self reqJSON];return;
 }
 //type別処理は例によって割愛
 lastid=[[idArr lastObject]longLongValue];
 [self mkSinglePostView];
}

できた。1100postくらいまでは動いてたけどerror code=12が出たのでメモリ関連の処理を調べる。postのuiviewで古いやつは配列から消したほうがいいのかな。
ランは遅かったので7.22km@37:51だけ走った。ラーメンは今月まだ10杯。ペース半減。体重はそれほど落ちず。

0 件のコメント:

コメントを投稿