簡體   English   中英

比較兩個“Uint8List”相等的正確快速方法是什么?

[英]What is the correct fast way to compare two `Uint8List`s' equality?

給定Uint8List a =...; Uint8List b =...; Uint8List a =...; Uint8List b =...; 我想比較它們的內容是否相同。 當然,我可以在 Flutter 中使用listEquals ,或者寫下一個簡單的循環,例如:

for (int index = 0; index < a.length; index += 1) {
    if (a[index] != b[index])
      return false;
  }

但是,鑒於Uint8List是一個非常特殊的數組,而且它通常很大,我猜哪里有更好(更快)的方法來做到這一點?

我認為您應該能夠通過一次比較 4 或 8 個字節來稍微加快速度(這也應該有 alignment 的好處)。 這應該不需要復制字節數據,因此不會產生明顯的 memory 損失。 我寫了一個快速實現來嘗試它:

import 'dart:typed_data';
import 'dart:math';

/// Naive [List] equality implementation.
bool listEquals<E>(List<E> list1, List<E> list2) {
  if (identical(list1, list2)) {
    return true;
  }

  if (list1.length != list2.length) {
    return false;
  }

  for (var i = 0; i < list1.length; i += 1) {
    if (list1[i] != list2[i]) {
      return false;
    }
  }
  return true;
}

/// Compares two [Uint8List]s by comparing 8 bytes at a time.
bool memEquals(Uint8List list1, Uint8List list2) {
  if (identical(list1, list2)) {
    return true;
  }

  if (list1.lengthInBytes != list2.lengthInBytes) {
    return false;
  }

  var numWords = list1.lengthInBytes ~/ 8;
  var reinterpretedList1 = list1.buffer.asUint64List(0, numWords);
  var reinterpretedList2 = list2.buffer.asUint64List(0, numWords);

  for (var i = 0; i < reinterpretedList1.length; i += 1) {
    if (reinterpretedList1[i] != reinterpretedList2[i]) {
      return false;
    }
  }

  // Compare any remaining bytes.
  for (var i = reinterpretedList1.lengthInBytes;
      i < list1.lengthInBytes;
      i += 1) {
    if (list1[i] != list2[i]) {
      return false;
    }
  }

  return true;
}

void main() {
  var random = Random();

  // Generate random data.
  //
  // 100 MB minus a few bytes to avoid being an exact multiple of 8 bytes.
  const numBytes = 100 * 1000 * 1000 - 3;
  var data = Uint8List.fromList([
    for (var i = 0; i < numBytes; i += 1) random.nextInt(256),
  ]);

  var dataCopy = Uint8List.fromList(data);

  var stopwatch = Stopwatch();
  stopwatch.start();
  var result = listEquals(data, dataCopy);
  print('Naive:     $result ${stopwatch.elapsed}');

  stopwatch.reset();
  stopwatch.start();
  result = memEquals(data, dataCopy);
  print('memEquals: $result ${stopwatch.elapsed}');
}

My empirical results from running it as a Dart console application on my 64-bit Linux machine ( dart mem_equals.dart ):

Naive:     true 0:00:00.152984
memEquals: true 0:00:00.038664

並從編譯它( dart compile exe mem_equals.dart && mem_equals.exe ):

Naive:     true 0:00:00.093478
memEquals: true 0:00:00.033560

Dart 的listEquals完全符合您的代碼的功能(加上一些快捷方式檢查),所以我會使用它而不是您自己的代碼,因為它更干凈。 一種可能的替代方法是將兩個列表都轉換為String並進行String相等比較。 我懷疑它是否更快(因為它創建了一個新的String ),但您可以輕松地對其進行基准測試並做出決定!

要將UInt8List轉換為String ,請使用

String s = String.fromCharCodes(inputAsUint8List);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM