2017-02-18 3 views
1

Im пытается создать функцию маски данных.Лучшие данные get/set uint8 по индексу/маскирование данных

Я нашел два способа:

  1. с использованием индексов данных

    • очень медленно
  2. создания массива из данных, изменить его, а затем преобразовать его обратно

    • ~ 70 раз быстрее
    • использует 2 раза больше памяти

Почему индексирование данных происходит так медленно? Есть ли лучший способ получить/установить uint8 по индексу без дублирования памяти?

вот мой тест:

var data = Data(bytes: [UInt8](repeating: 123, count: 100_000_000)) 

let a = CFAbsoluteTimeGetCurrent() 

// data masking 
for i in 0..<data.count { 
    data[i] = data[i] &+ 1 
} 

let b = CFAbsoluteTimeGetCurrent() 

// creating array 
var bytes = data.withUnsafeBytes { 
    [UInt8](UnsafeBufferPointer(start: $0, count: data.count)) 
} 
for i in 0..<bytes.count { 
    bytes[i] = bytes[i] &+ 1 
} 
data = Data(bytes: bytes) 

let c = CFAbsoluteTimeGetCurrent() 
print(b-a) // 8.8887130022049 
print(c-b) // 0.12415999174118 

ответ

1

Я не могу точно сказать, почему первый метод (с помощью индексации значения Data) настолько медленно. По данным Инструментов, много времени тратится в objc_msgSend при вызове методов на , лежащем в основе объекта NSMutableData.

Но вы можете мутировать байты без копирования данных в массив:

data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) -> Void in 
    for i in 0..<data.count { 
     bytes[i] = bytes[i] &+ 1 
    } 
} 

, который даже быстрее, чем ваш «копия на массив» метод.

На MacBook я получил следующие результаты:

  • индексирование данных: 7,15 сек
  • Копировать в массив и обратно: 0,238 сек
  • withUnsafeMutableBytes: 0,0659 сек
Смежные вопросы