LoginSignup
3
2

More than 5 years have passed since last update.

URLSession(NSURLSession)でpriorityは全く考慮されない件

Last updated at Posted at 2016-10-09

限られたコネクションリソースの中で、何を優先的にダウンロードするか?はユーザエクスペリエンス上重要になってくる場面も多いと思います。単純なfifo、lifoだけで制御できない要件の時に活用できそうな、priority項目の挙動について調査しました。

サマリ

  • ドキュメント: URLSessionTask
  • URLSessionTaskに設定するpriorityは全く考慮されない(無視されてる?)
  • 優先度制御は自分で実装するしかない
  • URLSessionのdelegateQueueはダウンロード順とは無関係(当たり前だけど)

実験したこと#1

placeimg.comでそこそこのサイズの画像を生成し、50個ダウンロードする。
25個はlowPriority、25個はhighPriority。
同時ダウンロード数はわかりやすいように1。
タスクの生成を終えてから一気にresume()。

コード

import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

var config = URLSessionConfiguration.ephemeral
config.httpMaximumConnectionsPerHost = 1

let session = URLSession(configuration: config)
var tasks = [URLSessionTask]()

for i in 1...50 {
    guard let url = URL(string: "http://placeimg.com/570/" + "90+i" + "/any") else {
        print("failed: \(i)")
        continue
    }
    let task = session.dataTask(with: url) { data, response, error in
        print("finished: \(i <= 25 ? "low" : "high") \(i)")
    }
    task.priority = i <= 25 ? URLSessionTask.lowPriority : URLSessionTask.highPriority

    tasks.append(task)
}

print("start resume")
tasks.forEach { $0.resume() }
print("end resume")

結果

priorityが考慮されず、resumeした順にダウンロードが開始されている模様。
本来であればpriorityが高い26-50のタスクが先に終わってほしいが、キレイに1-25が先に完了してしまっている。

start resume
end resume
finished: low 1
finished: low 2
finished: low 3
finished: low 4
finished: low 5
finished: low 6
finished: low 7
finished: low 8
finished: low 9
finished: low 10
finished: low 11
finished: low 12
finished: low 13
finished: low 14
finished: low 15
finished: low 16
finished: low 17
finished: low 18
finished: low 19
finished: low 20
finished: low 21
finished: low 22
finished: low 23
finished: low 24
finished: low 25
finished: high 26
finished: high 27
finished: high 28
finished: high 29
finished: high 30
finished: high 31
finished: high 32
finished: high 33
finished: high 34
finished: high 35
finished: high 36
finished: high 37
finished: high 38
finished: high 39
finished: high 40
finished: high 41
finished: high 42
finished: high 43
finished: high 44
finished: high 45
finished: high 46
finished: high 47
finished: high 48
finished: high 49
finished: high 50

実験したこと#2

URLSessionのイニシャライザに渡すOperationQueueのQoSを変更して確認。

コード

import Foundation
import PlaygroundSupport

PlaygroundPage.current.needsIndefiniteExecution = true

var config = URLSessionConfiguration.ephemeral
config.httpMaximumConnectionsPerHost = 1

var lowQueue = OperationQueue()
lowQueue.qualityOfService = .background

var highQueue = OperationQueue()
highQueue.qualityOfService = .userInteractive

let lowSession = URLSession(configuration: config, delegate: nil, delegateQueue: lowQueue)
let highSession = URLSession(configuration: config, delegate: nil, delegateQueue: highQueue)
var tasks = [URLSessionTask]()

for i in 1...50 {
    guard let url = URL(string: "http://placeimg.com/570/" + "90+i" + "/any") else {
        print("failed: \(i)")
        continue
    }

    let task = (i <= 25 ? lowSession : highSession).dataTask(with: url) { data, response, error in
        print("finished: \(i <= 25 ? "low" : "high") \(i)")
    }

    tasks.append(task)
}

print("start resume")
tasks.forEach { $0.resume() }
print("end resume")

結果

delegateQueueの設定はcompletionHandlerの実行優先度のはずなので、だめだとはおもったけどやはりだめでした。

start resume
end resume
finished: low 1
finished: low 2
finished: high 26
finished: low 3
finished: high 27
finished: low 4
finished: high 28
finished: low 5
finished: high 29
finished: low 6
finished: high 30
finished: low 7
finished: high 31
finished: low 8
finished: high 32
finished: low 9
finished: high 33
finished: low 10
finished: high 34
finished: low 11
finished: high 35
finished: low 12
finished: high 36
finished: low 13
finished: high 37
finished: low 14
finished: high 38
finished: low 15
finished: high 39
finished: high 40
finished: low 16
finished: low 17
finished: high 41
finished: low 18
finished: high 42
finished: low 19
finished: high 43
finished: low 20
finished: high 44
finished: low 21
finished: high 45
finished: low 22
finished: high 46
finished: low 23
finished: high 47
finished: low 24
finished: high 48
finished: low 25
finished: high 49
finished: high 50

どういうこと?

おそらくpriorityはただのプロパティで、次のtaskをresumeするときに自分で見て決めてねってことだと思います。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2