Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speedup diff-states by over 50x (6+ days -> under 3 hours) by removing old bottleneck #6107

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 52 additions & 78 deletions cmd/util/ledger/migrations/cadence_value_diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,9 +858,36 @@ func (dr *CadenceValueDiffReporter) diffCadenceDictionaryValue(
return true
})

onlyOldKeys, onlyNewKeys, sharedKeys := diffCadenceValues(vInterpreter, oldKeys, newKeys)
onlyOldKeys := make([]interpreter.Value, 0, len(oldKeys))

// Compare elements in both dict values

for _, key := range oldKeys {
valueTrace := trace.Append(fmt.Sprintf("[%v]", key))

oldValue, _ := v.Get(vInterpreter, interpreter.EmptyLocationRange, key)

newValue, found := otherDictionary.Get(otherInterpreter, interpreter.EmptyLocationRange, key)
if !found {
onlyOldKeys = append(onlyOldKeys, key)
continue
}

elementHasDifference := dr.diffValues(
vInterpreter,
oldValue,
otherInterpreter,
newValue,
domain,
valueTrace,
)
if elementHasDifference {
hasDifference = true
}
}

// Log keys only present in old dict value

if len(onlyOldKeys) > 0 {
hasDifference = true

Expand All @@ -878,42 +905,34 @@ func (dr *CadenceValueDiffReporter) diffCadenceDictionaryValue(
})
}

// Log field names only present in new composite value
if len(onlyNewKeys) > 0 {
hasDifference = true

dr.reportWriter.Write(
difference{
Address: dr.address.Hex(),
Domain: domain,
Kind: diffKindString[cadenceValueDiffKind],
Trace: trace.String(),
Msg: fmt.Sprintf(
"new dict value has %d elements with keys %v, that are not present in old dict value",
len(onlyNewKeys),
onlyNewKeys,
),
})
}

// Compare elements in both dict values
for _, key := range sharedKeys {
valueTrace := trace.Append(fmt.Sprintf("[%v]", key))
// Log keys only present in new dict value

oldValue, _ := v.Get(vInterpreter, interpreter.EmptyLocationRange, key)
if len(oldKeys) != len(newKeys) || len(onlyOldKeys) > 0 {
onlyNewKeys := make([]interpreter.Value, 0, len(newKeys))

newValue, _ := otherDictionary.Get(otherInterpreter, interpreter.EmptyLocationRange, key)
// find keys only present in new dict
for _, key := range newKeys {
found := v.ContainsKey(vInterpreter, interpreter.EmptyLocationRange, key)
if !found {
onlyNewKeys = append(onlyNewKeys, key)
}
}

elementHasDifference := dr.diffValues(
vInterpreter,
oldValue,
otherInterpreter,
newValue,
domain,
valueTrace,
)
if elementHasDifference {
if len(onlyNewKeys) > 0 {
hasDifference = true

dr.reportWriter.Write(
difference{
Address: dr.address.Hex(),
Domain: domain,
Kind: diffKindString[cadenceValueDiffKind],
Trace: trace.String(),
Msg: fmt.Sprintf(
"new dict value has %d elements with keys %v, that are not present in old dict value",
len(onlyNewKeys),
onlyNewKeys,
),
})
}
}

Expand Down Expand Up @@ -968,51 +987,6 @@ func diff[T comparable](old, new []T) (onlyOld, onlyNew, shared []T) {
return
}

func diffCadenceValues(oldInterpreter *interpreter.Interpreter, old, new []interpreter.Value) (onlyOld, onlyNew, shared []interpreter.Value) {
onlyOld = make([]interpreter.Value, 0, len(old))
onlyNew = make([]interpreter.Value, 0, len(new))
shared = make([]interpreter.Value, 0, min(len(old), len(new)))

sharedNew := make([]bool, len(new))

for _, o := range old {
found := false

for i, n := range new {
foundShared := false

if ev, ok := o.(interpreter.EquatableValue); ok {
if ev.Equal(oldInterpreter, interpreter.EmptyLocationRange, n) {
foundShared = true
}
} else {
if o == n {
foundShared = true
}
}

if foundShared {
shared = append(shared, o)
found = true
sharedNew[i] = true
break
}
}

if !found {
onlyOld = append(onlyOld, o)
}
}

for i, shared := range sharedNew {
if !shared {
onlyNew = append(onlyNew, new[i])
}
}

return
}

func min(a, b int) int {
if a <= b {
return a
Expand Down
Loading