optimize multi LPop and RPop

This commit is contained in:
今晚打老虎
2025-04-20 11:36:47 +08:00
committed by finley
parent 5851e662e0
commit 6640e6fad2
2 changed files with 77 additions and 35 deletions

View File

@@ -152,16 +152,14 @@ func undoLPop(db *DB, args [][]byte) []CmdLine {
if count > list.Len() {
count = list.Len()
}
elements := make([][]byte, count)
vals := list.Range(0, count)
var cmds []CmdLine
for i := len(vals) - 1; i >= 0; i-- {
cmds = append(cmds, CmdLine{
lPushCmd,
args[0],
vals[i].([]byte),
})
for i := 0; i < count; i++ {
elements[count-i-1] = vals[i].([]byte)
}
return cmds
cmd := CmdLine{lPushCmd, args[0]}
cmd = append(cmd, elements...)
return []CmdLine{cmd}
}
element, _ := list.Get(0).([]byte)
return []CmdLine{
@@ -456,16 +454,14 @@ func undoRPop(db *DB, args [][]byte) []CmdLine {
if count > list.Len() {
count = list.Len()
}
elements := make([][]byte, count)
vals := list.Range(list.Len()-count, list.Len())
var cmds []CmdLine
for i := 0; i < count; i++ {
cmds = append(cmds, CmdLine{
rPushCmd,
args[0],
vals[i].([]byte),
})
elements[i] = vals[i].([]byte)
}
return cmds
cmd := CmdLine{rPushCmd, args[0]}
cmd = append(cmd, elements...)
return []CmdLine{cmd}
}
element, _ := list.Get(list.Len() - 1).([]byte)
return []CmdLine{

View File

@@ -496,24 +496,47 @@ func TestUndoLPush(t *testing.T) {
func TestUndoLPop(t *testing.T) {
testDB.Flush()
key := utils.RandString(10)
value := utils.RandString(10)
testDB.Exec(nil, utils.ToCmdLine("lpush", key, value, value))
size := 10
values := make([]string, size)
pushArgs := []string{key}
for i := 0; i < size; i++ {
values[i] = utils.RandString(10)
pushArgs = append(pushArgs, values[i])
}
testDB.Exec(nil, utils.ToCmdLine2("lpush", pushArgs...))
result0 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
// test single lpop
cmdLine := utils.ToCmdLine("lpop", key)
undoCmdLines := undoLPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 2)
cmdLine = utils.ToCmdLine("lpop", key, strconv.Itoa(2))
undoCmdLines = undoRPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
asserts.AssertIntReply(t, result, 9)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 2)
asserts.AssertIntReply(t, result, size)
result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
if !utils.Equals(result0.ToBytes(), result.ToBytes()) {
t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes())
}
// test multi lpop
cmdLine = utils.ToCmdLine("lpop", key, strconv.Itoa(size))
undoCmdLines = undoLPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 0)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, size)
result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
if !utils.Equals(result0.ToBytes(), result.ToBytes()) {
t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes())
}
}
func TestUndoLSet(t *testing.T) {
@@ -535,24 +558,47 @@ func TestUndoLSet(t *testing.T) {
func TestUndoRPop(t *testing.T) {
testDB.Flush()
key := utils.RandString(10)
value := utils.RandString(10)
testDB.Exec(nil, utils.ToCmdLine("rpush", key, value, value))
size := 10
values := make([]string, size)
pushArgs := []string{key}
for i := 0; i < size; i++ {
values[i] = utils.RandString(10)
pushArgs = append(pushArgs, values[i])
}
testDB.Exec(nil, utils.ToCmdLine2("rpush", pushArgs...))
result0 := testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
// test single rpop
cmdLine := utils.ToCmdLine("rpop", key)
undoCmdLines := undoRPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 2)
cmdLine = utils.ToCmdLine("rpop", key, strconv.Itoa(2))
undoCmdLines = undoRPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
asserts.AssertIntReply(t, result, 9)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 2)
asserts.AssertIntReply(t, result, size)
result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
if !utils.Equals(result0.ToBytes(), result.ToBytes()) {
t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes())
}
// test multi rpop
cmdLine = utils.ToCmdLine("rpop", key, strconv.Itoa(size))
undoCmdLines = undoRPop(testDB, cmdLine[1:])
testDB.Exec(nil, cmdLine)
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, 0)
for _, cmdLine := range undoCmdLines {
testDB.Exec(nil, cmdLine)
}
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
asserts.AssertIntReply(t, result, size)
result = testDB.Exec(nil, utils.ToCmdLine("lrange", key, strconv.Itoa(0), strconv.Itoa(size)))
if !utils.Equals(result0.ToBytes(), result.ToBytes()) {
t.Errorf("expected %s, actually %s", result0.ToBytes(), result.ToBytes())
}
}
func TestUndoRPopLPush(t *testing.T) {