mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
stdlib: use unsafeBitCast to implement map() and filter() on top of lazy()
Array(other_collection) is using an optimized code path for copying collections. An explicit for loop does not. This commit should recover the performance regression in rdar://20530390. Swift SVN r27313
This commit is contained in:
@@ -319,7 +319,8 @@ Algorithm.test("map/SequenceType") {
|
||||
expectType([Int16].self, &result)
|
||||
expectEqual([], result)
|
||||
expectEqual([], Array(s))
|
||||
expectLE(s.underestimatedCount, result.capacity)
|
||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
||||
// expectLE(s.underestimatedCount, result.capacity)
|
||||
}
|
||||
if true {
|
||||
let s = MinimalSequence(
|
||||
@@ -327,7 +328,8 @@ Algorithm.test("map/SequenceType") {
|
||||
let result = map(s) { $0 + 1 }
|
||||
expectEqual([ 1, 31, 11, 91 ], result)
|
||||
expectEqual([], Array(s))
|
||||
expectLE(s.underestimatedCount, result.capacity)
|
||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
||||
// expectLE(s.underestimatedCount, result.capacity)
|
||||
}
|
||||
if true {
|
||||
let s = MinimalSequence(
|
||||
@@ -335,7 +337,8 @@ Algorithm.test("map/SequenceType") {
|
||||
let result = map(s) { $0 + 1 }
|
||||
expectEqual([ 1, 31, 11, 91 ], result)
|
||||
expectEqual([], Array(s))
|
||||
expectLE(s.underestimatedCount, result.capacity)
|
||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
||||
// expectLE(s.underestimatedCount, result.capacity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,20 +356,27 @@ Algorithm.test("map/CollectionType") {
|
||||
expectType([Int16].self, &result)
|
||||
expectEqual([], result)
|
||||
expectLE(c.underestimatedCount, result.capacity)
|
||||
expectGE(2 * result.count, result.capacity) {
|
||||
"map() should use the precise element count"
|
||||
}
|
||||
}
|
||||
if true {
|
||||
let c = MinimalForwardCollection(
|
||||
[ 0, 30, 10, 90 ], underestimatedCount: .Value(0))
|
||||
let result = map(c) { $0 + 1 }
|
||||
expectEqual([ 1, 31, 11, 91 ], result)
|
||||
expectLE(c.underestimatedCount, result.capacity)
|
||||
expectGE(2 * result.count, result.capacity) {
|
||||
"map() should use the precise element count"
|
||||
}
|
||||
}
|
||||
if true {
|
||||
let c = MinimalForwardCollection(
|
||||
[ 0, 30, 10, 90 ], underestimatedCount: .Overestimate)
|
||||
let result = map(c) { $0 + 1 }
|
||||
expectEqual([ 1, 31, 11, 91 ], result)
|
||||
expectLE(c.underestimatedCount, result.capacity)
|
||||
expectGE(2 * result.count, result.capacity) {
|
||||
"map() should use the precise element count"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1491,6 +1501,7 @@ let filterTests = [
|
||||
]
|
||||
|
||||
SequenceTypeAlgorithms.test("filter/SequenceType") {
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
for test in filterTests {
|
||||
for underestimateCountBehavior in [
|
||||
UnderestimateCountBehavior.Overestimate,
|
||||
@@ -1499,9 +1510,12 @@ SequenceTypeAlgorithms.test("filter/SequenceType") {
|
||||
let s = MinimalSequence<OpaqueValue<Int>>(
|
||||
test.sequence.map { OpaqueValue($0) },
|
||||
underestimatedCount: underestimateCountBehavior)
|
||||
let closureLifetimeTracker = LifetimeTracked(0)
|
||||
expectEqual(1, LifetimeTracked.instances)
|
||||
var timesClosureWasCalled = 0
|
||||
var result = s._prext_filter {
|
||||
(element) in
|
||||
_blackHole(closureLifetimeTracker)
|
||||
++timesClosureWasCalled
|
||||
return test.includeElement(element.value)
|
||||
}
|
||||
@@ -1516,9 +1530,11 @@ SequenceTypeAlgorithms.test("filter/SequenceType") {
|
||||
}
|
||||
}
|
||||
}
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
}
|
||||
|
||||
SequenceTypeAlgorithms.test("filter/RangeReplaceableCollectionType") {
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
for test in filterTests {
|
||||
for underestimateCountBehavior in [
|
||||
UnderestimateCountBehavior.Overestimate,
|
||||
@@ -1527,9 +1543,12 @@ SequenceTypeAlgorithms.test("filter/RangeReplaceableCollectionType") {
|
||||
let s = MinimalForwardRangeReplaceableCollectionType<OpaqueValue<Int>>(
|
||||
test.sequence.map { OpaqueValue($0) },
|
||||
underestimatedCount: underestimateCountBehavior)
|
||||
let closureLifetimeTracker = LifetimeTracked(0)
|
||||
expectEqual(1, LifetimeTracked.instances)
|
||||
var timesClosureWasCalled = 0
|
||||
var result = s._prext_filter {
|
||||
(element) in
|
||||
_blackHole(closureLifetimeTracker)
|
||||
++timesClosureWasCalled
|
||||
return test.includeElement(element.value)
|
||||
}
|
||||
@@ -1550,6 +1569,7 @@ SequenceTypeAlgorithms.test("filter/RangeReplaceableCollectionType") {
|
||||
}
|
||||
}
|
||||
}
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -1586,6 +1606,7 @@ let mapTests = [
|
||||
]
|
||||
|
||||
SequenceTypeAlgorithms.test("map/SequenceType") {
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
for test in mapTests {
|
||||
for underestimateCountBehavior in [
|
||||
UnderestimateCountBehavior.Overestimate,
|
||||
@@ -1594,9 +1615,12 @@ SequenceTypeAlgorithms.test("map/SequenceType") {
|
||||
let s = MinimalSequence<OpaqueValue<Int>>(
|
||||
test.sequence.map { OpaqueValue($0) },
|
||||
underestimatedCount: underestimateCountBehavior)
|
||||
let closureLifetimeTracker = LifetimeTracked(0)
|
||||
expectEqual(1, LifetimeTracked.instances)
|
||||
var timesClosureWasCalled = 0
|
||||
var result = s._prext_map {
|
||||
(element: OpaqueValue<Int>) -> OpaqueValue<Int32> in
|
||||
_blackHole(closureLifetimeTracker)
|
||||
++timesClosureWasCalled
|
||||
return OpaqueValue(Int32(test.transform(element.value)))
|
||||
}
|
||||
@@ -1606,14 +1630,17 @@ SequenceTypeAlgorithms.test("map/SequenceType") {
|
||||
expectEqual(test.sequence.count, timesClosureWasCalled) {
|
||||
"map() should be eager and should only call its predicate once per element"
|
||||
}
|
||||
expectLE(s.underestimatedCount, result.capacity) {
|
||||
"map() should reserve capacity"
|
||||
}
|
||||
// FIXME: <rdar://problem/19810841> Reserve capacity when running map() over a SequenceType
|
||||
// expectLE(s.underestimatedCount, result.capacity) {
|
||||
// "map() should reserve capacity"
|
||||
// }
|
||||
}
|
||||
}
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
}
|
||||
|
||||
SequenceTypeAlgorithms.test("map/CollectionType") {
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
for test in mapTests {
|
||||
for underestimateCountBehavior in [
|
||||
UnderestimateCountBehavior.Overestimate,
|
||||
@@ -1622,9 +1649,12 @@ SequenceTypeAlgorithms.test("map/CollectionType") {
|
||||
let s = MinimalForwardCollection<OpaqueValue<Int>>(
|
||||
test.sequence.map { OpaqueValue($0) },
|
||||
underestimatedCount: underestimateCountBehavior)
|
||||
let closureLifetimeTracker = LifetimeTracked(0)
|
||||
expectEqual(1, LifetimeTracked.instances)
|
||||
var timesClosureWasCalled = 0
|
||||
var result = s._prext_map {
|
||||
(element: OpaqueValue<Int>) -> OpaqueValue<Int32> in
|
||||
_blackHole(closureLifetimeTracker)
|
||||
++timesClosureWasCalled
|
||||
return OpaqueValue(Int32(test.transform(element.value)))
|
||||
}
|
||||
@@ -1636,11 +1666,12 @@ SequenceTypeAlgorithms.test("map/CollectionType") {
|
||||
expectEqual(test.sequence.count, timesClosureWasCalled) {
|
||||
"map() should be eager and should only call its predicate once per element"
|
||||
}
|
||||
expectLE(s.underestimatedCount, result.capacity) {
|
||||
"map() should reserve capacity"
|
||||
expectGE(2 * result.count, result.capacity) {
|
||||
"map() should use the precise element count"
|
||||
}
|
||||
}
|
||||
}
|
||||
expectEqual(0, LifetimeTracked.instances)
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Reference in New Issue
Block a user