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

force update #222

Open
ripienaar opened this issue Jun 28, 2020 · 6 comments
Open

force update #222

ripienaar opened this issue Jun 28, 2020 · 6 comments

Comments

@ripienaar
Copy link

ripienaar commented Jun 28, 2020

I used g.Update to append lines to a text box that scrolls - like a tail -f.

Periodically i remove lines from buffer so the size doesnt grow forever, however the fact that g.Update() creates a go routine leaks lots of memory over time. After a few 10k lines you end up with 10k go routines worth of descriptors in memory that will never be freed.

Editing the code and changing update to:

func (g *Gui) Update(f func(*Gui) error) {
	g.userEvents <- userEvent{f: f}
}

improves things for me drastically without impacting anything noticable. Can you perhaps tell me the reason why Update does this in a go routine? Might we add a SyncUpdate or similar that doesnt create a go routine?

@dsouzae
Copy link

dsouzae commented Jul 2, 2020

I implemented something similar but left the original Update function alone (for backwards compatibility), and created an "Update2" function of that does the same code.

Below is code I have to trim the maximum lines in the buffer, with some other bug fixes. I should make a PR for this.

diff --git a/view.go b/view.go
index 42082f8..0b81d66 100644
--- a/view.go
+++ b/view.go
@@ -71,6 +71,9 @@ type View struct {
        // If Mask is true, the View will display the mask instead of the real
        // content
        Mask rune
+
+       // Set the maximum number of lines to store
+       MaxLines int
 }
 
 type viewLine struct {
@@ -215,7 +218,7 @@ func (v *View) Write(p []byte) (n int, err error) {
                        }
                default:
                        cells := v.parseInput(ch)
-                       if cells == nil {
+                       if cells == nil || len(cells) <= 0 {
                                continue
                        }
 
@@ -227,6 +230,12 @@ func (v *View) Write(p []byte) (n int, err error) {
                        }
                }
        }
+
+       if v.MaxLines > 0 && len(v.lines) > v.MaxLines {
+               cut := len(v.lines) - v.MaxLines
+               v.lines = v.lines[cut:]
+       }
+
        return len(p), nil
 }
 
@@ -322,7 +331,7 @@ func (v *View) draw() error {
        }
 
        if v.Autoscroll && len(v.viewLines) > maxY {
-               v.oy = len(v.viewLines) - maxY
+               v.oy = len(v.viewLines) - maxY - 1
        }
        y := 0
        for i, vline := range v.viewLines {

@glvr182
Copy link

glvr182 commented Jul 3, 2020

I would be able to add a function called UpdateAsync(), this way we wouldn't change any existing code and still have the wanted functionalities.

What are your thoughts

@ripienaar
Copy link
Author

Ideally to avoid a unbounded growth it would be nice if there was a maxlines setting as suggested.

But yes, the UpdateAsync() would be great. If you agree with that I can send a PR

@glvr182
Copy link

glvr182 commented Jul 3, 2020

Yea totally! Go for it!

@glvr182
Copy link

glvr182 commented Jul 3, 2020

Can you open it on @awesome-gocui we run a fork of this project theere since the original ownwer hasnt responded to anything in a while

@ripienaar
Copy link
Author

OK, I opened awesome-gocui#67

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants