Skip to content

main.Buffer.ReOpen hangs for large binary files #1209

@jackwilsdon

Description

@jackwilsdon

Description of the problem or steps to reproduce

Call main.Buffer.ReOpen on a large binary file (e.g. the micro binary) and observe it hang completely.

You can try this out yourself by installing the filemanager plugin, running the tree command and attempting to open the micro binary with TAB.

Specifications

You can use micro -version to get the commit hash.

Commit hash: de35d00
OS: Ubuntu 18.04.1 LTS
Terminal: GNOME Terminal

Other Information

I've narrowed this down to the String() method of main.LineArray:

// Returns the String representation of the LineArray
func (la *LineArray) String() string {
str := ""
for i, l := range la.lines {
str += string(l.data)
if i != len(la.lines)-1 {
str += "\n"
}
}
return str
}

This method is called by main.EventHandler.ApplyDiff() (L89)

// ApplyDiff takes a string and runs the necessary insertion and deletion events to make
// the buffer equal to that string
// This means that we can transform the buffer into any string and still preserve undo/redo
// through insert and delete events
func (eh *EventHandler) ApplyDiff(new string) {
differ := dmp.New()
diff := differ.DiffMain(eh.buf.String(), new, false)
loc := eh.buf.Start()
for _, d := range diff {
if d.Type == dmp.DiffDelete {
eh.Remove(loc, loc.Move(Count(d.Text), eh.buf))
} else {
if d.Type == dmp.DiffInsert {
eh.Insert(loc, d.Text)
}
loc = loc.Move(Count(d.Text), eh.buf)
}
}
}

The issue is that eh.buf (in the case of the micro binary) is about 100k elements long, causing String() to pretty much crash the whole thing.

Attempted Fix

I tried changing this method to use the new strings.Builder but it did not seem to help.

Potential Solution

One potential solution I came up with is checking the equality of the old and new line arrays before diffing them, which is slow (takes maybe 1/4 a second) but doesn't hang micro completely.


This issues causes #1208 (filemanager calls ReOpen when opening a file for some reason).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions