diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/SortedCollections.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/SortedCollections.xcscheme
new file mode 100644
index 000000000..a660e5897
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/SortedCollections.xcscheme
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/swift-collections-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/swift-collections-Package.xcscheme
index bf3d7efa4..a3af5c698 100644
--- a/.swiftpm/xcode/xcshareddata/xcschemes/swift-collections-Package.xcscheme
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/swift-collections-Package.xcscheme
@@ -37,14 +37,14 @@
@@ -56,9 +56,9 @@
buildForAnalyzing = "YES">
@@ -70,9 +70,9 @@
buildForAnalyzing = "YES">
@@ -106,29 +106,29 @@
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
@@ -140,9 +140,9 @@
buildForAnalyzing = "YES">
@@ -194,6 +194,16 @@
ReferencedContainer = "container:">
+
+
+
+
+
+
+
+
+
+
+
+
insert",
+ input: [Int].self
+ ) { input in
+ input.withUnsafeBufferPointer { buffer in
+ cpp_map_insert_integers(buffer.baseAddress, buffer.count)
+ }
+ }
+
+ self.add(
+ title: "std::map successful find",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ let map = CppMap(input)
+ return { timer in
+ lookups.withUnsafeBufferPointer { buffer in
+ cpp_map_lookups(map.ptr, buffer.baseAddress, buffer.count)
+ }
+ }
+ }
}
}
diff --git a/Benchmarks/Benchmarks/SortedDictionaryBenchmarks.swift b/Benchmarks/Benchmarks/SortedDictionaryBenchmarks.swift
new file mode 100644
index 000000000..5af4c381d
--- /dev/null
+++ b/Benchmarks/Benchmarks/SortedDictionaryBenchmarks.swift
@@ -0,0 +1,303 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift Collections open source project
+//
+// Copyright (c) 2021 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import CollectionsBenchmark
+import SortedCollections
+
+extension Benchmark {
+ public mutating func addSortedDictionaryBenchmarks() {
+ self.add(
+ title: "SortedDictionary init(keysWithValues:)",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.map { (key: $0, value: 2 * $0) }
+
+ return { timer in
+ blackHole(SortedDictionary(keysWithValues: keysAndValues))
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary init(sortedKeysWithValues:)",
+ input: Int.self
+ ) { input in
+ let keysAndValues = (0.. sort, then init(sortedKeysWithValues:)",
+ input: [Int].self
+ ) { input in
+ return { timer in
+ var keysAndValues = input.map { (key: $0, value: 2 * $0) }
+
+ timer.measure {
+ keysAndValues.sort(by: { $0.key < $1.key })
+ blackHole(SortedDictionary(sortedKeysWithValues: keysAndValues))
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary sequential iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ for item in d {
+ blackHole(item)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary index-based iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ var i = d.startIndex
+ while i != d.endIndex {
+ blackHole(d[i])
+ d.formIndex(after: &i)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary offset-based iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ for offset in 0.. forEach iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ d.forEach({ blackHole($0) })
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary.Keys sequential iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ for item in d.keys {
+ blackHole(item)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary.Values sequential iteration",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ let d = SortedDictionary(keysWithValues: keysAndValues)
+
+ return { timer in
+ for item in d.values {
+ blackHole(item)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, successful lookups",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ let sortedDictionary = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ return { timer in
+ for key in lookups {
+ precondition(sortedDictionary[key] == key * 2)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, unsuccessful lookups",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ let sortedDictionary = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ let c = input.count
+ return { timer in
+ for key in lookups {
+ precondition(sortedDictionary[key + c] == nil)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, setter append",
+ input: [Int].self
+ ) { input in
+ let keysAndValues = input.lazy.map { (key: $0, value: 2 * $0) }
+ var sortedDictionary = SortedDictionary()
+
+ return { timer in
+ for (key, value) in keysAndValues {
+ sortedDictionary[key] = value
+ }
+ blackHole(sortedDictionary)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, setter noop",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ let c = input.count
+ timer.measure {
+ for i in lookups {
+ d[i + c] = nil
+ }
+ }
+ precondition(d.count == input.count)
+ blackHole(d)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, setter update",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ timer.measure {
+ for i in lookups {
+ d[i] = 0
+ }
+ }
+ precondition(d.count == input.count)
+ blackHole(d)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, setter remove",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ timer.measure {
+ for i in lookups {
+ d[i] = nil
+ }
+ }
+ precondition(d.count == 0)
+ blackHole(d)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, _modify insert",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary()
+
+ @inline(__always)
+ func modify(_ i: inout Int?, to value: Int?) {
+ i = value
+ }
+
+ timer.measure {
+ for i in lookups {
+ modify(&d[i], to: i * 2)
+ }
+ }
+
+ precondition(d.count == input.count)
+ blackHole(d)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, _modify update",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ timer.measure {
+ for i in lookups {
+ d[i]! *= 2
+ }
+ }
+ precondition(d.count == input.count)
+ blackHole(d)
+ }
+ }
+
+ self.add(
+ title: "SortedDictionary subscript, _modify remove",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ return { timer in
+ var d = SortedDictionary(
+ keysWithValues: input.map { ($0, 2 * $0) })
+
+ @inline(__always)
+ func modify(_ i: inout Int?, to value: Int?) {
+ i = value
+ }
+
+ timer.measure {
+ for i in lookups {
+ modify(&d[i], to: nil)
+ }
+ }
+
+ precondition(d.count == 0)
+ blackHole(d)
+ }
+ }
+ }
+}
diff --git a/Benchmarks/Benchmarks/SortedSetBenchmarks.swift b/Benchmarks/Benchmarks/SortedSetBenchmarks.swift
new file mode 100644
index 000000000..be4555d4d
--- /dev/null
+++ b/Benchmarks/Benchmarks/SortedSetBenchmarks.swift
@@ -0,0 +1,207 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift Collections open source project
+//
+// Copyright (c) 2021 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import CollectionsBenchmark
+import SortedCollections
+
+extension Benchmark {
+ public mutating func addSortedSetBenchmarks() {
+ self.addSimple(
+ title: "SortedSet init from range",
+ input: Int.self
+ ) { size in
+ blackHole(SortedSet(0 ..< size))
+ }
+
+ self.addSimple(
+ title: "SortedSet init(sortedElements:) from range",
+ input: Int.self
+ ) { size in
+ blackHole(SortedSet(sortedElements: 0 ..< size))
+ }
+ self.add(
+ title: "SortedSet sequential iteration",
+ input: [Int].self
+ ) { input in
+ let set = SortedSet(input)
+ return { timer in
+ for i in set {
+ blackHole(i)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedSet forEach iteration",
+ input: [Int].self
+ ) { input in
+ let set = SortedSet(input)
+ return { timer in
+ set.forEach { i in
+ blackHole(i)
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedSet successful contains",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ let set = SortedSet(input)
+ return { timer in
+ for i in lookups {
+ precondition(set.contains(i))
+ }
+ }
+ }
+
+ self.add(
+ title: "SortedSet unsuccessful contains",
+ input: ([Int], [Int]).self
+ ) { input, lookups in
+ let set = SortedSet(input)
+ let lookups = lookups.map { $0 + input.count }
+ return { timer in
+ for i in lookups {
+ precondition(!set.contains(i))
+ }
+ }
+ }
+
+ self.addSimple(
+ title: "SortedSet insertions",
+ input: [Int].self
+ ) { input in
+ var set: SortedSet = []
+ for i in input {
+ set.insert(i)
+ }
+ precondition(set.count == input.count)
+ blackHole(set)
+ }
+
+ self.add(
+ title: "SortedSet remove",
+ input: ([Int], [Int]).self
+ ) { input, removals in
+ return { timer in
+ var set = SortedSet(input)
+ timer.measure {
+ for i in removals {
+ set.remove(i)
+ }
+ }
+ precondition(set.isEmpty)
+ blackHole(set)
+ }
+ }
+
+ self.add(
+ title: "SortedSet removeLast",
+ input: Int.self
+ ) { size in
+ return { timer in
+ var set = SortedSet(0 ..< size)
+ timer.measure {
+ for _ in 0 ..< size {
+ set.removeLast()
+ }
+ }
+ precondition(set.isEmpty)
+ blackHole(set)
+ }
+ }
+
+ self.add(
+ title: "SortedSet removeFirst",
+ input: Int.self
+ ) { size in
+ return { timer in
+ var set = SortedSet(0 ..< size)
+ timer.measure {
+ for _ in 0 ..< size {
+ set.removeFirst()
+ }
+ }
+ precondition(set.isEmpty)
+ blackHole(set)
+ }
+ }
+
+ let overlaps: [(String, (Int) -> Int)] = [
+ ("0%", { c in c }),
+ ("25%", { c in 3 * c / 4 }),
+ ("50%", { c in c / 2 }),
+ ("75%", { c in c / 4 }),
+ ("100%", { c in 0 }),
+ ]
+
+ // SetAlgebra operations with Self
+ do {
+ for (percentage, start) in overlaps {
+ self.add(
+ title: "SortedSet union with Self (\(percentage) overlap)",
+ input: [Int].self
+ ) { input in
+ let start = start(input.count)
+ let a = SortedSet(input)
+ let b = SortedSet(start ..< start + input.count)
+ return { timer in
+ blackHole(a.union(b))
+ }
+ }
+ }
+
+ for (percentage, start) in overlaps {
+ self.add(
+ title: "SortedSet intersection with Self (\(percentage) overlap)",
+ input: [Int].self
+ ) { input in
+ let start = start(input.count)
+ let a = SortedSet(input)
+ let b = SortedSet(start ..< start + input.count)
+ return { timer in
+ blackHole(a.intersection(b))
+ }
+ }
+ }
+
+ for (percentage, start) in overlaps {
+ self.add(
+ title: "SortedSet symmetricDifference with Self (\(percentage) overlap)",
+ input: [Int].self
+ ) { input in
+ let start = start(input.count)
+ let a = SortedSet(input)
+ let b = SortedSet(start ..< start + input.count)
+ return { timer in
+ blackHole(a.symmetricDifference(b))
+ }
+ }
+ }
+
+ for (percentage, start) in overlaps {
+ self.add(
+ title: "SortedSet subtracting Self (\(percentage) overlap)",
+ input: [Int].self
+ ) { input in
+ let start = start(input.count)
+ let a = SortedSet(input)
+ let b = SortedSet(start ..< start + input.count)
+ return { timer in
+ blackHole(a.subtracting(b))
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/Benchmarks/CppBenchmarks/include/MapBenchmarks.h b/Benchmarks/CppBenchmarks/include/MapBenchmarks.h
new file mode 100644
index 000000000..f02db76be
--- /dev/null
+++ b/Benchmarks/CppBenchmarks/include/MapBenchmarks.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift Collections open source project
+//
+// Copyright (c) 2021 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CPPBENCHMARKS_MAP_BENCHMARKS_H
+#define CPPBENCHMARKS_MAP_BENCHMARKS_H
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Create a std::map, populating it with data from the supplied buffer.
+/// Returns an opaque pointer to the created instance.
+extern void *cpp_map_create(const intptr_t *start, size_t count);
+
+/// Destroys an ordered map previously returned by `cpp_map_create`.
+extern void cpp_map_destroy(void *ptr);
+
+extern void cpp_map_insert_integers(const intptr_t *start, size_t count);
+
+extern void cpp_map_lookups(void *ptr, const intptr_t *start, size_t count);
+extern void cpp_map_subscript(void *ptr, const intptr_t *start, size_t count);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* CPPBENCHMARKS_MAP_BENCHMARKS_H */
diff --git a/Benchmarks/CppBenchmarks/include/module.modulemap b/Benchmarks/CppBenchmarks/include/module.modulemap
index 7fbcf9332..900b0f1ab 100644
--- a/Benchmarks/CppBenchmarks/include/module.modulemap
+++ b/Benchmarks/CppBenchmarks/include/module.modulemap
@@ -5,6 +5,7 @@ module CppBenchmarks {
header "DequeBenchmarks.h"
header "UnorderedSetBenchmarks.h"
header "UnorderedMapBenchmarks.h"
+ header "MapBenchmarks.h"
header "PriorityQueueBenchmarks.h"
export *
}
diff --git a/Benchmarks/CppBenchmarks/src/MapBenchmarks.cpp b/Benchmarks/CppBenchmarks/src/MapBenchmarks.cpp
new file mode 100644
index 000000000..60488b78c
--- /dev/null
+++ b/Benchmarks/CppBenchmarks/src/MapBenchmarks.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift Collections open source project
+//
+// Copyright (c) 2021 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+#include "MapBenchmarks.h"
+#include