| 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 | |
| 38 | foreach {num cmd enc title} { |
| 39 | 16 lpush ziplist "Ziplist" |
| 40 | 1000 lpush linkedlist "Linked list" |
| 41 | 10000 lpush linkedlist "Big Linked list" |
| 42 | 16 sadd intset "Intset" |
| 43 | 1000 sadd hashtable "Hash table" |
| 44 | 10000 sadd hashtable "Big Hash table" |
| 45 | } { |
| 46 | set result [create_random_dataset $num $cmd] |
| 47 | assert_encoding $enc tosort |
| 48 | |
| 49 | test "$title: SORT BY key" { |
| 50 | assert_equal $result [r sort tosort BY weight_*] |
| 51 | } |
| 52 | |
| 53 | test "$title: SORT BY hash field" { |
| 54 | assert_equal $result [r sort tosort BY wobj_*->weight] |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | set result [create_random_dataset 16 lpush] |
| 59 | test "SORT GET #" { |
| 60 | assert_equal [lsort -integer $result] [r sort tosort GET #] |
| 61 | } |
| 62 | |
| 63 | test "SORT GET <const>" { |
| 64 | r del foo |
| 65 | set res [r sort tosort GET foo] |
| 66 | assert_equal 16 [llength $res] |
| 67 | foreach item $res { assert_equal {} $item } |
| 68 | } |
| 69 | |
| 70 | test "SORT GET (key and hash) with sanity check" { |
| 71 | set l1 [r sort tosort GET # GET weight_*] |
| 72 | set l2 [r sort tosort GET # GET wobj_*->weight] |
| 73 | foreach {id1 w1} $l1 {id2 w2} $l2 { |
| 74 | assert_equal $id1 $id2 |
| 75 | assert_equal $w1 [r get weight_$id1] |
| 76 | assert_equal $w2 [r get weight_$id1] |
| 77 | } |
| 78 | } |
| 79 | |
| 80 | test "SORT BY key STORE" { |
| 81 | r sort tosort BY weight_* store sort-res |
| 82 | assert_equal $result [r lrange sort-res 0 -1] |
| 83 | assert_equal 16 [r llen sort-res] |
| 84 | assert_encoding ziplist sort-res |
| 85 | } |
| 86 | |
| 87 | test "SORT BY hash field STORE" { |
| 88 | r sort tosort BY wobj_*->weight store sort-res |
| 89 | assert_equal $result [r lrange sort-res 0 -1] |
| 90 | assert_equal 16 [r llen sort-res] |
| 91 | assert_encoding ziplist sort-res |
| 92 | } |
| 93 | |
| 94 | test "SORT DESC" { |
| 95 | assert_equal [lsort -decreasing -integer $result] [r sort tosort DESC] |
| 96 | } |
| 97 | |
| 98 | test "SORT ALPHA against integer encoded strings" { |
| 99 | r del mylist |
| 100 | r lpush mylist 2 |
| 101 | r lpush mylist 1 |
| 102 | r lpush mylist 3 |
| 103 | r lpush mylist 10 |
| 104 | r sort mylist alpha |
| 105 | } {1 10 2 3} |
| 106 | |
| 107 | test "SORT sorted set" { |
| 108 | r del zset |
| 109 | r zadd zset 1 a |
| 110 | r zadd zset 5 b |
| 111 | r zadd zset 2 c |
| 112 | r zadd zset 10 d |
| 113 | r zadd zset 3 e |
| 114 | r sort zset alpha desc |
| 115 | } {e d c b a} |
| 116 | |
| 117 | test "SORT sorted set: +inf and -inf handling" { |
| 118 | r del zset |
| 119 | r zadd zset -100 a |
| 120 | r zadd zset 200 b |
| 121 | r zadd zset -300 c |
| 122 | r zadd zset 1000000 d |
| 123 | r zadd zset +inf max |
| 124 | r zadd zset -inf min |
| 125 | r zrange zset 0 -1 |
| 126 | } {min c a b d max} |
| 127 | |
| 128 | test "SORT regression for issue #19, sorting floats" { |
| 129 | r flushdb |
| 130 | set floats {1.1 5.10 3.10 7.44 2.1 5.75 6.12 0.25 1.15} |
| 131 | foreach x $floats { |
| 132 | r lpush mylist $x |
| 133 | } |
| 134 | assert_equal [lsort -real $floats] [r sort mylist] |
| 135 | } |
| 136 | |
| 137 | tags {"slow"} { |
| 138 | set num 100 |
| 139 | set res [create_random_dataset $num lpush] |
| 140 | |
| 141 | test "SORT speed, $num element list BY key, 100 times" { |
| 142 | set start [clock clicks -milliseconds] |
| 143 | for {set i 0} {$i < 100} {incr i} { |
| 144 | set sorted [r sort tosort BY weight_* LIMIT 0 10] |
| 145 | } |
| 146 | set elapsed [expr [clock clicks -milliseconds]-$start] |
| 147 | if {$::verbose} { |
| 148 | puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " |
| 149 | flush stdout |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | test "SORT speed, $num element list BY hash field, 100 times" { |
| 154 | set start [clock clicks -milliseconds] |
| 155 | for {set i 0} {$i < 100} {incr i} { |
| 156 | set sorted [r sort tosort BY wobj_*->weight LIMIT 0 10] |
| 157 | } |
| 158 | set elapsed [expr [clock clicks -milliseconds]-$start] |
| 159 | if {$::verbose} { |
| 160 | puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " |
| 161 | flush stdout |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | test "SORT speed, $num element list directly, 100 times" { |
| 166 | set start [clock clicks -milliseconds] |
| 167 | for {set i 0} {$i < 100} {incr i} { |
| 168 | set sorted [r sort tosort LIMIT 0 10] |
| 169 | } |
| 170 | set elapsed [expr [clock clicks -milliseconds]-$start] |
| 171 | if {$::verbose} { |
| 172 | puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " |
| 173 | flush stdout |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | test "SORT speed, $num element list BY <const>, 100 times" { |
| 178 | set start [clock clicks -milliseconds] |
| 179 | for {set i 0} {$i < 100} {incr i} { |
| 180 | set sorted [r sort tosort BY nokey LIMIT 0 10] |
| 181 | } |
| 182 | set elapsed [expr [clock clicks -milliseconds]-$start] |
| 183 | if {$::verbose} { |
| 184 | puts -nonewline "\n Average time to sort: [expr double($elapsed)/100] milliseconds " |
| 185 | flush stdout |
| 186 | } |
| 187 | } |
| 188 | } |
| 189 | } |