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

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

# サマリ
- ドキュメント: [URLSessionTask] (https://developer.apple.com/reference/foundation/urlsessiontask)
- URLSessionTaskに設定するpriorityは全く考慮されない(無視されてる？)
- 優先度制御は自分で実装するしかない
- URLSessionのdelegateQueueはダウンロード順とは無関係(当たり前だけど)

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

# コード
```swift
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を変更して確認。

# コード
```swift
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するときに自分で見て決めてねってことだと思います。