Pregunta Asignar variable de conteo sobre llamar a .count en Array en Swift


Ocasionalmente llego a un lugar donde no cambiaré el contenido de una matriz, pero necesito saber su conteo varias veces sobre una función. ¿Es más eficiente asignar el .count de la matriz a una variable y usarla varias veces, o el compilador hace que la eficiencia sea equivalente?


5
2017-08-24 17:57


origen


Respuestas:


¡A investigar! Es myArray.count es equivalente a acceder a una propiedad almacenada o es una propiedad computada que realiza algunos cálculos "innecesarios" si se llama repetidamente para una matriz no mutada? (Haciendo caso omiso de la inteligencia del compilador)

/// The number of elements in the array.
public var count: Int {
  return _getCount()
}

// ... what is function _getCount()?

internal func _getCount() -> Int {
  return _buffer.count
}

// ... what is property _buffer?
internal var _buffer: _Buffer

// ... what is type _Buffer? (Swift)
internal typealias _Buffer = _ContiguousArrayBuffer<Element>

// ... what is type _ContiguousArrayBuffer?
// --> switch source file
import SwiftShims

/// Class used whose sole instance is used as storage for empty
/// arrays.  The instance is defined in the runtime and statically
/// initialized.  See stdlib/runtime/GlobalObjects.cpp for details.
internal struct _ContiguousArrayBuffer<Element> : _ArrayBufferProtocol {

  // ... conformance to _ArrayBufferProtocol

  /// The number of elements the buffer stores.
  internal var count: Int {
    get {
      return __bufferPointer.header.count
    }
    // ...
  }   
  // ...
}

// ... what is property __bufferPointer?
var __bufferPointer: ManagedBufferPointer<_ArrayBody, Element>

// what is type _ArrayBody?
// we notice for now that it is used in the following class:
internal final class _EmptyArrayStorage
  : _ContiguousArrayStorageBase {
  // ...

  var countAndCapacity: _ArrayBody // telling name for a tuple? :)
}

// --> proceed to core/ArrayBody.swift
import SwiftShims

// ...

internal struct _ArrayBody {
  var _storage: _SwiftArrayBodyStorage

  // ...

  /// The number of elements stored in this Array.
  var count: Int {
    get {
      return _assumeNonNegative(_storage.count)
    }
    set(newCount) {
      _storage.count = newCount
    }
  } 
}

// we are near our price! we need to look closer at  _SwiftArrayBodyStorage, 
// the type of _storage, so lets look at SwiftShims, GlobalObjects.cpp
// (as mentioned in source comments above), specifically
// --> switch source file
struct _SwiftArrayBodyStorage {
  __swift_intptr_t count;              
  __swift_uintptr_t _capacityAndFlags;
};

// Yay, we found a stored property!

Entonces al final count es una propiedad almacenada y no se calcula por llamada, por lo que no debería ser una razón para almacenar explícitamente arr.count propiedad por ti mismo.


3
2017-08-24 19:24



struct _SwiftArrayBodyStorage {
    __swift_intptr_t count;
    __swift_uintptr_t _capacityAndFlags;
};

Esta es la estructura que Swift implementa. De acuerdo con este recuento, siempre se sabe cuántos elementos hay en el búfer. Probablemente puedas usar eso

formulario de información: https://ankit.im/swift/2016/01/08/exploring-swift-array-implementation/

editar para más información

public var count: Int {
  get {
    return __bufferPointer.value.count
  }
  nonmutating set {
     _sanityCheck(newValue >= 0)

     _sanityCheck(
        newValue <= capacity,
        "Can't grow an array buffer past its capacity")

        __bufferPointer._valuePointer.memory.count = newValue
    }
}

2
2017-08-24 18:06



No importa; Sugeriría hacer lo que sea que haga su código más simple y fácil de entender. En las versiones de lanzamiento, el optimizador debe estar en línea y notar que el valor será el mismo en todas las llamadas. Independientemente, Array.count es básicamente equivalente en rendimiento / código para acceder a una variable local.


1
2017-08-24 18:15



Array.count es un valor precomputado. Ya que no lo calcula sobre la marcha, es mucho menos trabajo usarlo que usar la memoria para almacenarlo por segunda vez. Aun así, ninguno de los dos métodos debería importar a menos que se haga en millones.


0
2018-02-08 15:39