sort.tcl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. start_server {
  2. tags {"sort"}
  3. overrides {
  4. "list-max-ziplist-value" 16
  5. "list-max-ziplist-entries" 32
  6. "set-max-intset-entries" 32
  7. }
  8. } {
  9. proc create_random_dataset {num cmd} {
  10. set tosort {}
  11. set result {}
  12. array set seenrand {}
  13. r del tosort
  14. for {set i 0} {$i < $num} {incr i} {
  15. # Make sure all the weights are different because
  16. # Redis does not use a stable sort but Tcl does.
  17. while 1 {
  18. randpath {
  19. set rint [expr int(rand()*1000000)]
  20. } {
  21. set rint [expr rand()]
  22. }
  23. if {![info exists seenrand($rint)]} break
  24. }
  25. set seenrand($rint) x
  26. r $cmd tosort $i
  27. r set weight_$i $rint
  28. r hset wobj_$i weight $rint
  29. lappend tosort [list $i $rint]
  30. }
  31. set sorted [lsort -index 1 -real $tosort]
  32. for {set i 0} {$i < $num} {incr i} {
  33. lappend result [lindex $sorted $i 0]
  34. }
  35. set _ $result
  36. }
  37. foreach {num cmd enc title} {
  38. 16 lpush ziplist "Ziplist"
  39. 1000 lpush linkedlist "Linked list"
  40. 10000 lpush linkedlist "Big Linked list"
  41. 16 sadd intset "Intset"
  42. 1000 sadd hashtable "Hash table"
  43. 10000 sadd hashtable "Big Hash table"
  44. } {
  45. set result [create_random_dataset $num $cmd]
  46. assert_encoding $enc tosort
  47. test "$title: SORT BY key" {
  48. assert_equal $result [r sort tosort BY weight_*]
  49. }
  50. test "$title: SORT BY hash field" {
  51. assert_equal $result [r sort tosort BY wobj_*->weight]
  52. }
  53. }
  54. set result [create_random_dataset 16 lpush]
  55. test "SORT GET #" {
  56. assert_equal [lsort -integer $result] [r sort tosort GET #]
  57. }
  58. test "SORT GET <const>" {
  59. r del foo
  60. set res [r sort tosort GET foo]
  61. assert_equal 16 [llength $res]
  62. foreach item $res { assert_equal {} $item }
  63. }
  64. test "SORT GET (key and hash) with sanity check" {
  65. set l1 [r sort tosort GET # GET weight_*]
  66. set l2 [r sort tosort GET # GET wobj_*->weight]
  67. foreach {id1 w1} $l1 {id2 w2} $l2 {
  68. assert_equal $id1 $id2
  69. assert_equal $w1 [r get weight_$id1]
  70. assert_equal $w2 [r get weight_$id1]
  71. }
  72. }
  73. test "SORT BY key STORE" {
  74. r sort tosort BY weight_* store sort-res
  75. assert_equal $result [r lrange sort-res 0 -1]
  76. assert_equal 16 [r llen sort-res]
  77. assert_encoding ziplist sort-res
  78. }
  79. test "SORT BY hash field STORE" {
  80. r sort tosort BY wobj_*->weight store sort-res
  81. assert_equal $result [r lrange sort-res 0 -1]
  82. assert_equal 16 [r llen sort-res]
  83. assert_encoding ziplist sort-res
  84. }
  85. test "SORT DESC" {
  86. assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC]
  87. }
  88. test "SORT ALPHA against integer encoded strings" {
  89. r del mylist
  90. r lpush mylist 2
  91. r lpush mylist 1
  92. r lpush mylist 3
  93. r lpush mylist 10
  94. r sort mylist alpha
  95. } {1 10 2 3}
  96. test "SORT sorted set" {
  97. r del zset
  98. r zadd zset 1 a
  99. r zadd zset 5 b
  100. r zadd zset 2 c
  101. r zadd zset 10 d
  102. r zadd zset 3 e
  103. r sort zset alpha desc
  104. } {e d c b a}
  105. test "SORT sorted set: +inf and -inf handling" {
  106. r del zset
  107. r zadd zset -100 a
  108. r zadd zset 200 b
  109. r zadd zset -300 c
  110. r zadd zset 1000000 d
  111. r zadd zset +inf max
  112. r zadd zset -inf min
  113. r zrange zset 0 -1
  114. } {min c a b d max}
  115. test "SORT regression for issue #19, sorting floats" {
  116. r flushdb
  117. set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15}
  118. foreach x $floats {
  119. r lpush mylist $x
  120. }
  121. assert_equal [lsort -real $floats] [r sort mylist]
  122. }
  123. tags {"slow"} {
  124. set num 100
  125. set res [create_random_dataset $num lpush]
  126. test "SORT speed, $num element list BY key, 100 times" {
  127. set start [clock clicks -milliseconds]
  128. for {set i 0} {$i < 100} {incr i} {
  129. set sorted [r sort tosort BY weight_* LIMIT 0 10]
  130. }
  131. set elapsed [expr [clock clicks -milliseconds]-$start]
  132. if {$::verbose} {
  133. puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
  134. flush stdout
  135. }
  136. }
  137. test "SORT speed, $num element list BY hash field, 100 times" {
  138. set start [clock clicks -milliseconds]
  139. for {set i 0} {$i < 100} {incr i} {
  140. set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10]
  141. }
  142. set elapsed [expr [clock clicks -milliseconds]-$start]
  143. if {$::verbose} {
  144. puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
  145. flush stdout
  146. }
  147. }
  148. test "SORT speed, $num element list directly, 100 times" {
  149. set start [clock clicks -milliseconds]
  150. for {set i 0} {$i < 100} {incr i} {
  151. set sorted [r sort tosort LIMIT 0 10]
  152. }
  153. set elapsed [expr [clock clicks -milliseconds]-$start]
  154. if {$::verbose} {
  155. puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
  156. flush stdout
  157. }
  158. }
  159. test "SORT speed, $num element list BY <const>, 100 times" {
  160. set start [clock clicks -milliseconds]
  161. for {set i 0} {$i < 100} {incr i} {
  162. set sorted [r sort tosort BY nokey LIMIT 0 10]
  163. }
  164. set elapsed [expr [clock clicks -milliseconds]-$start]
  165. if {$::verbose} {
  166. puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds "
  167. flush stdout
  168. }
  169. }
  170. }
  171. }