AndroidでHttpモジュールを使用してHttpのGETでバイナリファイルをダウンロードしたところ、80M相当で数分かかりました。
こちらHttpモジュールの設定等で高速化が可能でしょうか?
現状はReadバッファサイズとスレッド更新頻度を下記の機能で調整しようとしていますが、期待する速度が現在出ていません。
FHttpModule::SetMaxReadBufferSize(); FHttpModule::SetHttpThreadTickRate();
のスレッドも確認したのですが、Androidに関しては有益な情報が見つかりませんでした。
※エディター上では速度的な問題はでていません。
PierPop
(Pier Pop)
2
Httpを使用したネットワーク機能自体に既知の不具合があります(UE_33732)。
明確な要因や回避策まで特定できていないため、設定等による高速化を実現することはできかねるかと思われます。
以下のバグレポートを追跡して下さい。
宜しくお願いします。
-similar problem
-issue
Pier Poops さん、回答ありがとうございます。
Unreal Engine Issues and Bug Tracker (UE-33732) を確認した限りでは、エンジン側の対応待ちになりますね。
AndroidではWindowsと同様にLibCurlが使用されています。
実装を読んだ限りだと特にcurlオプションの指定等で問題となるような記述は見受けられませんでした。
手元にAndroid実機が無いため検証はできていないのですが、もしかすると受け取ったレスポンスをバッファにコピーする部分がボトルネックになっているのかもしれません。
ボトルネックになりそうな実装は以下の部分です。
1.FCurlHttpRequest::ReceiveResponseBodyCallback にて受け取ったレスポンスを Response->Payload にコピーしているのですが、Payloadのサイズが設定されていないために、大きなデータを受信した場合に何度もメモリの再確保が発生する可能性があります。
こちらはサイズを設定するAPIが提供されていないため、エンジンコードに手を入れる必要がありますが、FCurlHttpResponse::Payload の初期化タイミングで適切なサイズを確保してあげることで再確保を防ぐことが可能だと思われます。
2.もしも FCurlHttpResponse::GetContentAsString を使用されている場合、文字列変換のためにPayloadと同サイズのテンポラリ配列にコピーする上に、FString形式で戻り値を返す際に更にコピーが発生しています。
今回はバイナリファイルのダウンロードとのことなので文字列変換は必要無いため、GetContentAsString ではなく GetContent を使用しているかどうかをご確認ください。
HogeTatu さん、回答ありがとうございます。
2.の方はGetContentを使用していますので、問題ないと思います。
1.の方ですが、当方でもソースを確認したところ、Response->Payload.AddUninitialized 処理内の ResizeGrow(Array.h)の実装によってはメモリの再確保に問題がありそうに感じました。
※ArrayMaxを頻繁に超えるようなAddがあるとパフォーマンスが落ちる?
※実際10K前後のファイルのダウンロードにはそれほど時間がかかっていません。
※ゲームで使用する場合は、FCurlHttpResponseでの受信データをテンポラリファイルに書き込む方が良いかもしれません。
現状調査を続けていますが、まだ解決には至っていません。
確かに大きなサイズのレスポンスを扱う場合、テンポラリファイルに書き込んでバッファサイズが大きくならないようにするのは良いかもしれませんね。
ちなみにまだしっかり把握できていないのですが、エンジンのRuntimeモジュールにNetworkFileというものが存在します。
軽く読んだ限りだとネットワーク上に存在するファイルをHTTPもしくはTCPでダウンロードし、ローカルにキャッシュする仕組みのように見受けられます。
レスポンスをメモリに乗せるHTTPモジュールと比較すると用途に合っているかもしれないので、こちらもご確認ください。
mayonezu
(ou shinjyo)
7
HogeTatuさん、1について、Response->PayloadをReceiveResponseHeaderCallbackのContentLengthを取得したタイミングでサイズを確保する処理に変えて検証してみたが、Android実機上の速度は前とほぼ変化なしだったので原因はここではなかったのかもしれません、2についてはGetContentを使用していますので問題ないです。上の返事にご提示いただいたNetworkFileのほうも確認させていただきます。
なるほど…。それは残念です。こちらでもまた何かわかったら共有させて頂きます。