Problemas de rendimiento en la búsqueda de valores mínimos y máximos utilizando métodos funcionales

Descripción simplificada del problema

tengo una matriz de sub - vistas, y quiero encontrar las etiquetas más bajas y más altas (~ Min y Max). Intenté usar el enfoque funcional de SWIFT y lo optimicé todo lo que sabía, pero cuando lo hice:
let startVals = (min:Int.max, max:Int.min)
var minMax:(min: Int, max: Int) = subviews.filter({$0 is T2GCell}).reduce(startVals) {
        (min($0.min, $1.tag), max($0.max, $1.tag))
}
Mi rendimiento sigue siendo inferior al de un buen ol en el bucle (aproximadamente 10 veces más lento):
var lowest2 = Int.max
var highest2 = Int.min
for view in subviews {
    if let cell = view as? T2GCell {
        lowest2 = lowest2 > cell.tag ? cell.tag : lowest2
        highest2 = highest2 < cell.tag ? cell.tag : highest2
    }
}
Para ser precisos, también he incluido fragmentos de código de medición. Tenga en cuenta que el "recalculado"del tiempo legible por el ser humano se realiza fuera de cualquier medida:
let startDate: NSDate = NSDate()

// code

let endDate: NSDate = NSDate()

// outside of measuring block
let dateComponents: NSDateComponents = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!.components(NSCalendarUnit.CalendarUnitNanosecond, fromDate: startDate, toDate: endDate, options: NSCalendarOptions(0))
let time = Double(Double(dateComponents.nanosecond) / 1000000.0)
¿Mi pregunta es... Estoy equivocado, o este caso de uso simplemente no encaja en el enfoque funcional?
Editar
Esto es dos veces más lento:
var extremes = reduce(lazy(subviews).map({$0.tag}), startValues) {
    (min($0.lowest, $1), max($0.highest, $1))
}
Esto es sólo un 20% más lento:
var extremes2 = reduce(lazy(subviews), startValues) {
    (min($0.lowest, $1.tag), max($0.highest, $1.tag))
}
Reducir y comprimir a un buen tiempo de rendimiento, pero todavía no tan rápido como el Bucle for.
Edición 2
Me di cuenta de que había perdido el filter en mi edición anterior. Cuando se añade:
var extremes3 = reduce(lazy(subviews).filter({$0 is T2GCell}), startValues) {
    (min($0.lowest, $1.tag), max($0.highest, $1.tag))
}
Mi actuación es el doble de lenta. En la versión optimizada,

La mejor manera de resolver el problema

y reduce deben tener exactamente el mismo rendimiento. Sin embargo, en versiones de depuración no optimizadas, el bucle for puede ser mejor que la versión for, ya que reduce no se especializará e incrustará. Los filtros pueden ser removidos para eliminar la creación innecesaria de matrices adicionales, pero la creación de matrices será muy rápida (todo lo que hace es copiar el puntero a la memoria), por lo que esto no es realmente un gran problema, y la eliminación es más importante para la claridad.
Sin embargo, creo que parte del problema es que en reduce, usted llama a la propiedad reduce en .tag, y en la versión de bucle AnyObject, usted llama a for. Esto puede hacer una gran diferencia. Si abre el filtro, puede ver:
// filtered will be of type [AnyObject]
let filtered = subviews.filter({$0 is T2GCell})

let minMax:(min: Int, max: Int) = filtered.reduce(startVals) {
    // so $1.tag is calling AnyObject.tag, not T2GCell.tag
    (min($0.min, $1.tag), max($0.max, $1.tag))
}
Esto significa que T2GCell.tag se enlazará dinámicamente en tiempo de ejecución, lo que puede ser una operación más lenta.
Aquí hay un código de ejemplo que muestra esta diferencia. Si compila este .tag, verá que los bucles swiftc -O y reduce enlazados estáticamente se ejecutan básicamente de la misma manera:
import Foundation

@objc class MyClass: NSObject {
    var someProperty: Int
    init(_ x: Int) { someProperty = x }
}
let classes: [AnyObject] = (0..<10_000).map { _ in MyClass(Int(arc4random())) }

func timeRun<T>(name: String, f: ()->T) -> String {
    let start = CFAbsoluteTimeGetCurrent()
    let result = f()
    let end = CFAbsoluteTimeGetCurrent()
    let timeStr = toString(Int((end - start) * 1_000_000))
    return "\(name)\t\(timeStr)µs, produced \(result)"
}

let runs = [
    ("Using AnyObj.someProperty", { 
        reduce(classes, 0) { prev,next in max(prev,next.someProperty) } 
    }),
    ("Using MyClass.someProperty", { 
        reduce(classes, 0) { prev,next in 
          (next as? MyClass).map { max(prev,$0.someProperty) } ?? prev 
        }
    }),
    ("Using plain ol' for loop", {
        var maxSoFar = 0
        for obj in classes {
            if let mc = obj as? MyClass {
                maxSoFar = max(maxSoFar, mc.someProperty)
            }
        }
        return maxSoFar
    }),
]

println("\n".join(map(runs, timeRun)))
Salida en mi máquina:
Using AnyObj.someProperty       4115µs, produced 4294310151
Using MyClass.someProperty      1169µs, produced 4294310151
Using plain ol' for loop        1178µs, produced 4294310151