iOS ネットワーク速度検出ソリューション

バックグラウンド

ネットワークの状況に基づいてより詳細なビジネス戦略を立てるには、現在のネットワークの状況を可能な限り低コストで評価するための一連のネットワーク速度検出ソリューションが必要です.したがって、検出データは過去のネットワークリクエストから取得されることを願っています.正確に評価するためにネットワーク リクエストにリソースを費やすのではなく、

指数計算

通常、ネットワーク速度の主な評価指標として RTT が使用されますが、過去のリクエスト RTT 値のバッチを取得した後、より正確な目標 RTT 値を計算するにはどうすればよいですか?

RTT 値に影響を与える変数は主に次のとおりです。

  1. ネットワークの状態は時間とともに変化します。
  2. リクエストはさまざまなサーバーから送信され、パフォーマンスも異なり、ロングテール データの影響を受けやすくなります。

最初に Chrome の nqe ソース コードを参照してください: chromium.googlesource.com/chromium/sr…

重量設計

関連するソース コードを調べた後、過去のリクエストの RTT 値が最終的な計算の重みに関連付けられることがわかり、RTT の重みを計算するためのコア ロジックが見つかりました。

void ObservationBuffer::ComputeWeightedObservations(
    const base::TimeTicks& begin_timestamp,
    int32_t current_signal_strength,
    std::vector<WeightedObservation>* weighted_observations,
    double* total_weight) const {
…
    base::TimeDelta time_since_sample_taken = now - observation.timestamp();
    double time_weight =
        pow(weight_multiplier_per_second_, time_since_sample_taken.InSeconds());

    double signal_strength_weight = 1.0;
    if (current_signal_strength >= 0 && observation.signal_strength() >= 0) {
      int32_t signal_strength_weight_diff =
          std::abs(current_signal_strength - observation.signal_strength());
      signal_strength_weight =
          pow(weight_multiplier_per_signal_level_, signal_strength_weight_diff);
    }

    double weight = time_weight * signal_strength_weight;复制代码

重みは主に次の 2 つの側面から生じることがわかります。

  1. 信号の重み: 現在の信号強度との差が大きいほど、RTT 値の基準値が低くなります。
  2. 時間重み: 現在時刻からの RTT 値が長いほど、基準値が低くなります。

このプロセスにより、時間の経過とともに変化するネットワーク条件の影響を軽減できます。

半減期設計

2 つの重みを計算するときは、pow(衰减因子, diff)計算が使用されるため、この「減衰係数」を取得する方法は、時間減衰係数を例にとります。

double GetWeightMultiplierPerSecond(
    const std::map<std::string, std::string>& params) {
  // Default value of the half life (in seconds) for computing time weighted
  // percentiles. Every half life, the weight of all observations reduces by
  // half. Lowering the half life would reduce the weight of older values
  // faster.
  int half_life_seconds = 60;
  int32_t variations_value = 0;
  auto it = params.find("HalfLifeSeconds");
  if (it != params.end() && base::StringToInt(it->second, &variations_value) &&
      variations_value >= 1) {
    half_life_seconds = variations_value;
  }
  DCHECK_GT(half_life_seconds, 0);
  return pow(0.5, 1.0 / half_life_seconds);
}
复制代码

実際には、半減期を設計し、「1 秒あたりの減衰率」を計算することです.たとえば、RTT 値と現在時刻の差が 60 秒の場合、重みは初期値の半分に減衰します。さらに考えてみると、次の 2 つの結論を導き出すことができます。

  1. 同じ過去の RTT 値レベルでは、半減期が短いほど信頼性が高くなります。これは、現在のネットワーク ステータスに近いためです。
  2. 同じ半減期の下では、過去の RTT 値の大きさが大きいほど信頼性が高くなります。これは、サーバーのパフォーマンスの違いが平滑化されるためです。

さらに一歩進んで、過去のRTT値の大きさに応じて半減期を調整し、それらの間のバランスを見つけることができます.

重み付けアルゴリズムの設計

重みを取得した後の重みの計算方法は、加重平均アルゴリズムを思い浮かべる可能性が最も高いですが、ロングテール データの影響も受けます。

例えば、あるRTT値が正常値の何十倍も大きく重みが少し高い場合、加重平均値も大きくなるので、加重中央値を求めるのも良い方法で、これも同様のアプローチです。 nqe.疑似コードは次のとおりです。

//按 RTT 值从小到大排序
samples.sort()
//目标权重是总权重的一半
desiredWeight = 0.5 * totalWeight
//找到目标权重对应的 RTT 值
cumulativeWeight = 0
for sample in samples
  cumulativeWeight += sample.weight
  If (cumulativeWeight >= desiredWeight) 
    return sample.RTT
复制代码

さらなる最適化

過去のネットワーク リクエストのサンプル データから重み付けされた中央値を計算し、計算された RTT 値の範囲に応じて、業務用のネットワーク速度ステータスを決定します。最適化されます。

ネットワーク アクセスのないシナリオ

ユーザーが一定期間ネットワークにアクセスせず、サンプル データが不足している場合、リアルタイムで RTT 値を計算する要求を開始するアクティブな検出戦略が導入されます。

ネットワーク状態の急速な悪化

ある瞬間にネットワークが突然貧弱になり、大量のリクエストがキューに蓄積された場合、RTT 値はネットワーク リクエストのランディングに依存するため、この時点で計算される目標 RTT 値にはラグが生じます。

この問題を解決するために、「着荷していないリクエスト」のキューを記録することができます. 毎回RTT値を計算する前に、「一定の閾値を超えている」「一定の割合を超えている」未着のリクエストが存在することを事前に判断します.ネットワークの状態が弱いと判断された場合、ネットワークの劣化をいち早く察知する効果を発揮します。

おすすめ

転載: juejin.im/post/7171020344117952542
おすすめ