-
Notifications
You must be signed in to change notification settings - Fork 63
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
FactoryVecDeque will eventually crash due to memory leaks #619
Comments
Relm4:use gtk::prelude::*;
use item::Item;
use relm4::{
factory::{FactoryComponent, FactoryVecDeque, FactoryView},
gtk,
prelude::*,
FactorySender,
};
use std::time::Duration;
fn main() {
gtk::init().unwrap();
let app = relm4::main_application();
RelmApp::from_app(app).run::<List>(());
}
pub struct List {
items: FactoryVecDeque<Item>,
}
#[derive(Debug)]
pub enum ListInput {
Update,
}
impl SimpleComponent for List {
type Init = ();
type Input = ListInput;
type Output = ();
type Root = gtk::ApplicationWindow;
type Widgets = ();
fn init_root() -> Self::Root {
gtk::ApplicationWindow::builder().build()
}
fn init(
_init: Self::Init,
root: Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let list = gtk::Box::builder().build();
root.set_child(Some(&{
let container = gtk::ScrolledWindow::builder().build();
container.set_child(Some(&list));
container
}));
let items = FactoryVecDeque::builder().launch(list).detach();
let model = Self { items };
std::thread::spawn({
let sender = sender.clone();
move || loop {
sender.input(ListInput::Update);
std::thread::sleep(Duration::from_secs(1));
}
});
ComponentParts { widgets: (), model }
}
fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
match message {
ListInput::Update => {
let mut guard = self.items.guard();
guard.clear();
for _ in 0..10000 {
guard.push_back(Item {});
}
}
}
}
}
mod item {
use super::*;
#[derive(Clone)]
pub struct Item;
type RootWidget = gtk::Box;
#[derive(Debug)]
pub struct FactoryWidgets {}
impl FactoryComponent for Item {
type Init = Self;
type Input = ();
type Output = ();
type CommandOutput = ();
type ParentWidget = gtk::Box;
type Root = RootWidget;
type Widgets = FactoryWidgets;
type Index = DynamicIndex;
fn init_root(&self) -> Self::Root {
RootWidget::builder()
.hexpand(false)
.vexpand(true)
.halign(gtk::Align::Start)
.build()
}
fn init_widgets(
&mut self,
_index: &DynamicIndex,
_root_widget: Self::Root,
_returned_widget: &<Self::ParentWidget as FactoryView>::ReturnedWidget,
_sender: FactorySender<Self>,
) -> Self::Widgets {
Self::Widgets {}
}
fn init_model(value: Self::Init, _index: &DynamicIndex, _sender: FactorySender<Self>) -> Self {
value
}
}
} GTK4:use gtk::{prelude::*, Application, ApplicationWindow};
use relm4::{prelude::gtk, RelmRemoveAllExt};
use std::time::Duration;
fn main() {
let application = Application::builder()
.application_id("com.example.list")
.build();
application.connect_activate(|app| {
let window = ApplicationWindow::builder()
.application(app)
.default_width(400)
.default_height(400)
.build();
window.set_child(Some(&{
let container = gtk::ScrolledWindow::builder().build();
container.set_child(Some(&{
let list = gtk::Box::builder().build();
gtk::glib::timeout_add_local(Duration::from_secs(1), {
let list = gtk::glib::clone::Downgrade::downgrade(&list);
move || {
let Some(list) = list.upgrade()
else {
return false.into();
};
list.remove_all();
for _ in 0..10000 {
list.append(&{ gtk::Box::builder().build() });
}
true.into()
}
});
list
}));
container
}));
window.show();
});
application.run();
} |
Thanks for the report. This is actually not quite unexpected because Since we just published version 0.7 and 0.8, would you mind checking whether the problem exists there as well? |
@AaronErhardt I first found this issue with Relm 0.6 and was going to report the issue, but I just learned that Relm 0.7/0.8 has just been released (Congratulations!🎉) So I upgraded my crate in hopes that this issue had been resolved, but alas, it was not. |
The leak seems to be caused by gtk-rs-core and is simply triggered very often by Relm4s factories. Let's see what the gtk-rs devs say about this (you can follow the referenced issue). |
Thank you! |
The memory leak should be fixed in gtk-rs in their latest versions. Can you confirm whether it works now? |
Oh, I have confirmed that it has been fixed. Thanks a lot! |
Hello. Thanks for the great library.
I am building a viewer that handles a large number of images(<10000) and after rewriting the contents of
FactoryVecDeque
several times, the performance of the application slows down significantly.While investigating this, I found a memory leak which I am not sure if it is related to the performance drop, but I have confirmed that it will eventually crash.
(I am a GTK4 contributor on macOS and believe that additional research is still needed to determine if Relm4 is related to the performance degradation)
When I created code with similar behavior using only gtk4, the program did not have any memory leaks.
This also occurs in relm4 version 0.6
Relm4:
GTK4 Only:
The text was updated successfully, but these errors were encountered: