@@ -161,7 +161,12 @@ func randint(lo, hi int) int {
161161
162162func BenchmarkSort8 (b * testing.B ) {
163163 for _ , count := range []int {1e3 , 1e4 , 1e5 , 1e6 } {
164- b .Run (strconv .Itoa (count ), benchSort (count , 8 , random , nil ))
164+ b .Run ("random-" + strconv .Itoa (count ), benchSort (count , 8 , 0 , random , nil ))
165+ if count > 1e4 {
166+ b .Run ("partially-ordered(10)-" + strconv .Itoa (count ), benchSort (count , 8 , 10 , random , nil ))
167+ b .Run ("partially-ordered(100)-" + strconv .Itoa (count ), benchSort (count , 8 , 100 , random , nil ))
168+ b .Run ("partially-ordered(1000)-" + strconv .Itoa (count ), benchSort (count , 8 , 1000 , random , nil ))
169+ }
165170 }
166171}
167172
@@ -182,62 +187,103 @@ func stdlibSort8(b *testing.B, size int) {
182187 }
183188}
184189
190+ func stdlibSort8PartiallySorted (b * testing.B , size int , partitions int ) {
191+ // 8 bytes per int64
192+ b .SetBytes (8 * int64 (size ))
193+ data := make ([]int64 , size )
194+ // panic if not a whole number
195+ partitionSize := int (size / partitions )
196+ partitionOrder := rand .Perm (partitions )
197+ groupedPartitions := make ([][]int64 , partitions )
198+
199+ for i := 0 ; i < len (groupedPartitions ); i ++ {
200+ partition := make ([]int64 , partitionSize )
201+ for j := 0 ; j < len (partition ); j ++ {
202+ partition [j ] = int64 (rand .Intn (size / 10 ))
203+ }
204+ sort .Slice (partition , func (i , j int ) bool { return partition [i ] < partition [j ] })
205+ groupedPartitions [partitionOrder [i ]] = partition
206+ }
207+
208+ partiallyOrdered := make ([]int64 , size )
209+ for _ , partition := range groupedPartitions {
210+ partiallyOrdered = append (partiallyOrdered , partition ... )
211+ }
212+
213+ b .StopTimer ()
214+ for i := 0 ; i < b .N ; i ++ {
215+ copy (data , partiallyOrdered )
216+ b .StartTimer ()
217+ sort .Slice (data , func (i , j int ) bool { return data [i ] < data [j ] })
218+ b .StopTimer ()
219+ }
220+ }
221+
185222func BenchmarkStdlibSort8 (b * testing.B ) {
186223 for _ , size := range []int {1e5 , 1e6 } {
187- b .Run (strconv .Itoa (size ), func (b * testing.B ) {
224+ b .Run ("random-" + strconv .Itoa (size ), func (b * testing.B ) {
188225 stdlibSort8 (b , size )
189226 })
227+ b .Run ("partially-sorted(10)-" + strconv .Itoa (size ), func (b * testing.B ) {
228+ stdlibSort8PartiallySorted (b , size , 10 )
229+ })
230+ b .Run ("partially-sorted(100)-" + strconv .Itoa (size ), func (b * testing.B ) {
231+ stdlibSort8PartiallySorted (b , size , 100 )
232+ })
233+ b .Run ("partially-sorted(1000)-" + strconv .Itoa (size ), func (b * testing.B ) {
234+ stdlibSort8PartiallySorted (b , size , 1000 )
235+ })
190236 }
191237}
192238
193239func BenchmarkSort8Indirect (b * testing.B ) {
194240 swap := func (int , int ) {}
195241 const count = 100000
196- b .Run ("random" , benchSort (count , 8 , random , swap ))
197- b .Run ("asc" , benchSort (count , 8 , asc , swap ))
198- b .Run ("desc" , benchSort (count , 8 , desc , swap ))
242+ b .Run ("random" , benchSort (count , 8 , 0 , random , swap ))
243+ b .Run ("asc" , benchSort (count , 8 , 0 , asc , swap ))
244+ b .Run ("desc" , benchSort (count , 8 , 0 , desc , swap ))
199245}
200246
201247func BenchmarkSort16 (b * testing.B ) {
202248 for _ , count := range []int {1e3 , 1e4 , 1e5 , 1e6 } {
203- b .Run (strconv .Itoa (count ), benchSort (count , 16 , random , nil ))
249+ b .Run (strconv .Itoa (count ), benchSort (count , 16 , 0 , random , nil ))
204250 }
205251}
206252
207253func BenchmarkSort16Indirect (b * testing.B ) {
208254 swap := func (int , int ) {}
209255 const count = 100000
210- b .Run ("random" , benchSort (count , 16 , random , swap ))
211- b .Run ("asc" , benchSort (count , 16 , asc , swap ))
212- b .Run ("desc" , benchSort (count , 16 , desc , swap ))
256+ b .Run ("random" , benchSort (count , 16 , 0 , random , swap ))
257+ b .Run ("asc" , benchSort (count , 16 , 0 , asc , swap ))
258+ b .Run ("desc" , benchSort (count , 16 , 0 , desc , swap ))
213259}
214260
215261func BenchmarkSort24 (b * testing.B ) {
216262 for _ , count := range []int {1e3 , 1e4 , 1e5 , 1e6 } {
217- b .Run (strconv .Itoa (count ), benchSort (count , 24 , random , nil ))
263+ b .Run (strconv .Itoa (count ), benchSort (count , 24 , 0 , random , nil ))
218264 }
219265}
220266
221267func BenchmarkSort24Indirect (b * testing.B ) {
222268 swap := func (int , int ) {}
223269 const count = 100000
224- b .Run ("random" , benchSort (count , 24 , random , swap ))
225- b .Run ("asc" , benchSort (count , 24 , asc , swap ))
226- b .Run ("desc" , benchSort (count , 24 , desc , swap ))
270+ b .Run ("random" , benchSort (count , 24 , 0 , random , swap ))
271+ b .Run ("asc" , benchSort (count , 24 , 0 , asc , swap ))
272+ b .Run ("desc" , benchSort (count , 24 , 0 , desc , swap ))
227273}
228274
229275func BenchmarkSort32 (b * testing.B ) {
230276 for _ , count := range []int {1e3 , 1e4 , 1e5 , 1e6 } {
231- b .Run (strconv .Itoa (count ), benchSort (count , 32 , random , nil ))
277+ b .Run (strconv .Itoa (count ), benchSort (count , 0 , 32 , random , nil ))
232278 }
233279}
234280
235281func BenchmarkSort32Indirect (b * testing.B ) {
236282 swap := func (int , int ) {}
237283 const count = 100000
238- b .Run ("random" , benchSort (count , 32 , random , swap ))
239- b .Run ("asc" , benchSort (count , 32 , asc , swap ))
240- b .Run ("desc" , benchSort (count , 32 , desc , swap ))
284+ b .Run ("random" , benchSort (count , 32 , 0 , random , swap ))
285+ b .Run ("asc" , benchSort (count , 32 , 0 , asc , swap ))
286+ b .Run ("desc" , benchSort (count , 32 , 0 , desc , swap ))
241287}
242288
243289type order int
@@ -246,9 +292,10 @@ const (
246292 random order = iota
247293 asc
248294 desc
295+ partiallyOrdered
249296)
250297
251- func benchSort (count , size int , order order , indirect func (int , int )) func (* testing.B ) {
298+ func benchSort (count , size , partitions int , order order , indirect func (int , int )) func (* testing.B ) {
252299 return func (b * testing.B ) {
253300 b .StopTimer ()
254301 buf := make ([]byte , count * size )
@@ -266,6 +313,23 @@ func benchSort(count, size int, order order, indirect func(int, int)) func(*test
266313 }
267314 }
268315
316+ if order == partiallyOrdered {
317+ // panic if not a whole number
318+ partitionSize := int ((count * size ) / partitions )
319+ partitionOrder := rand .Perm (partitions )
320+ groupedPartitions := make ([][]byte , partitions )
321+
322+ for i := 0 ; i < len (groupedPartitions ); i ++ {
323+ partition := make ([]byte , partitionSize )
324+ sort .Sort (newGeneric (partition , partitionSize , nil ))
325+ groupedPartitions [partitionOrder [i ]] = partition
326+ }
327+
328+ for _ , partition := range groupedPartitions {
329+ unsorted = append (unsorted , partition ... )
330+ }
331+ }
332+
269333 b .SetBytes (int64 (len (buf )))
270334
271335 for i := 0 ; i < b .N ; i ++ {
0 commit comments