内存使用GWT应用程序 [英] Memory usage of a GWT application

查看:85
本文介绍了内存使用GWT应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在研究GWT应用程序,作为未来项目技术的证明。我喜欢用Java代替JavaScript构建AJAX代码的方式。但是当我重复调用RPC服务时,我似乎遇到了内存问题。浏览器的内存使用量不断增长和增长。

在Google上搜索时,我一直在阅读GWT有多伟大,并且不可能得到内存泄漏,因此任何人都可以解释为什么我的浏览器(Firefox和Chromium)的内存在快速增长?



感谢您提前帮助我,
Bram



代码:

  ... 

class ExampleTable继承了Composite

private RPCService rpcService;
私人定时器tableUpdater;
$ b公共ExampleTable(){
... Init计时器和RPC服务
...添加组件
initWidget();


private void getTableDataFromRPCService(){
this.rpcService.getData(new AsyncCallback< ArrayList< Data>>(){

@覆盖
public void onSuccess(ArrayList< Data> result){
ExampleTable.this.updateTable(result);
}

@Override
public void onFailure(Throwable caught){
//什么也不做
}
});
}
$ b $ private void updateTable(ArrayList< Data> tableData){
...更新表
}

private void startUpdateTask (){
this.serviceUpdater = new Timer(){
@Override
public void run(){
ExampleTable.this.getTableDataFromRPCService();
}
};
serviceUpdater.scheduleRepeating(2000);


编辑:



我花了一些时间来编写一个可以下载的测试应用程序 这里。在启用了表更新之后,我运行了大约半小时的应用程序,之后Firefox花费了大约350MB的内存。我还在禁用更新表的情况下运行了测试,一小时后,Firefox的内存使用量略微超过了100MB。


$ b (要运行此示例,您需要Google可视化API GWT可以从Google下载,但由于新的用户政策,我不允许发布该链接)



我刚下班回家,开始另一个测试,没有表格数据更新以查看内存使用情况是否持续增长或者是否停止在特定时间点。

这是客户端实现类(GWTMemoryIssue.java):

  public class GWTMemoryIssue implements EntryPoint {
//使用或不使用表
运行private static final boolean WITH_TABLE = false;

private final TestServiceAsync rpcService = GWT.create(TestService.class);

私人面板;
私人定时器定时器;
私人表格表;

public void onModuleLoad(){
RootPanel rootPanel = RootPanel.get();

this.panel = new VerticalPanel();
this.panel.setSize(100%,100%);

rootPanel.add(panel);

if(WITH_TABLE){
loadTable();
} else {
startUpdateTask();



$ b private void startUpdateTask(){
this.timer = new Timer(){

@覆盖
public void run(){
GWTMemoryIssue.this.getTableData();

}
};
this.timer.scheduleRepeating(2000);

$ b $ public void loadTable(){
Runnable onLoadCallback = new Runnable(){
public void run(){
GWTMemoryIssue.this.table = new Table(createTableData(),createTableOptions());
GWTMemoryIssue.this.table.setSize(100%,100%);
GWTMemoryIssue.this.panel.add(GWTMemoryIssue.this.table);
GWTMemoryIssue.this.startUpdateTask();
}
};

VisualizationUtils.loadVisualizationApi(onLoadCallback,Table.PACKAGE);


private选项createTableOptions(){
选项options = Options.create();

返回选项;


private DataTable createTableData(){
DataTable data = DataTable.create();

data.addColumn(ColumnType.STRING,Name);
data.addColumn(ColumnType.NUMBER,Intval 1);
data.addColumn(ColumnType.NUMBER,Intval 2);
data.addColumn(ColumnType.NUMBER,Intval 3);

返回数据;

$ b $ private void getTableData(){
rpcService.getListOfItems(new AsyncCallback< ArrayList< ListItem>>(){
public void onFailure(Throwable caught) {
//什么也不做
}

public void onSuccess(ArrayList< ListItem> result){
if(WITH_TABLE){
GWTMemoryIssue.this。 updateTableData(result);
} else {
//忽略来自服务器的数据
}
}
});
}

private void updateTableData(ArrayList< ListItem> result){
DataTable data = createTableData();

data.addRows(result.size());

int row = 0;
for(ListItem li:result){
data.setValue(row,0,li.getName());
data.setValue(row,1,li.getIntVal());
data.setValue(row,2,li.getIntSecondVal());
data.setValue(row,3,li.getThirdIntVal());
row ++;
}

this.table.draw(data,createTableOptions());
}
}


解决方案

您在这里提供的所有附加信息都是一些想法。我猜想内存增加是由内存中剩余的列表引起的。有可能内存没有被释放,或者JavaScript垃圾收集器没有时间清理,因为更新之间的时间间隔很短。以下是您可以执行的一些测试:


  1. 要测试垃圾收集器是否没有时间调整您的代码,以使更新仅运行有限次数,然后检查内存使用是否在几分钟内减少。如果内存使用量减少,那么在现实世界的例子中,这可能不是一个问题。但简单地通过设置延迟时间为30秒来测试它。

  2. 在使用清单后可以帮助清理垃圾收集器:我不知道什么效果最好,所以在这里有一些建议:从列表中删除对象,或者遍历列表并将值设置为null。这在正常情况下不是必需的,因为垃圾收集器会这样做。

您也可以尝试以下Firefox内存配置文件添加 - 查看是否可以找到增加的内存: http:// ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on


I'm currently working on a GWT application as a proof of technology for future projects. I like the way of building my AJAX code in Java instead of JavaScript. But I seem to be running into a memory problem when I repeat calls to an RPC service. The browser memory usage keeps growing and growing.

When searching Google I keep reading about how great GWT is and that its impossible to get memory leaks so can anyone explain why my browser (Firefox and Chromium) memory is rocketing?

Thanks in advance for helping me, Bram

The code:

...

class ExampleTable extends Composite

  private RPCService rpcService;
  private Timer tableUpdater;

  public ExampleTable(){
   ... Init timer and RPC Service
   ... Add components
   initWidget();
  }

  private void getTableDataFromRPCService() {
  this.rpcService.getData(new AsyncCallback<ArrayList<Data>>() {

      @Override
      public void onSuccess(ArrayList<Data> result) {
          ExampleTable.this.updateTable(result);
      }

      @Override
      public void onFailure(Throwable caught) {
          //Do nothing
      }
  });
  }

  private void updateTable(ArrayList<Data> tableData){
    ... Update the table
  }

  private void startUpdateTask() {
      this.serviceUpdater = new Timer() {
          @Override
          public void run() {
            ExampleTable.this.getTableDataFromRPCService();
          }
      };
      serviceUpdater.scheduleRepeating(2000);
  }
}

EDIT:

I've spent some time to write a test application which can be downloaded here. I ran the application for about half an hour with the table update enabled after that Firefox took about 350MB of memory. I also ran the test with the update table disabled for an hour memory usage in Firefox went to little over 100MB.

(To run this sample you need the Google visualization API for GWT which can be downloaded from Google but I'm not allowed to post the link because of a new user policy )

I just got home from work and start another test without the table data update to see if memory usage keeps increasing or if it stops at a certain point.

This is the client implementation class (GWTMemoryIssue.java):

public class GWTMemoryIssue implements EntryPoint {
//Run with or without table
private static final boolean WITH_TABLE = false; 

private final TestServiceAsync rpcService = GWT.create(TestService.class);

private Panel panel;
private Timer timer;
private Table table;

public void onModuleLoad() {
    RootPanel rootPanel = RootPanel.get();

    this.panel = new VerticalPanel();
    this.panel.setSize("100%", "100%");

    rootPanel.add(panel);

    if (WITH_TABLE) {
        loadTable();
    }else{
        startUpdateTask();
    }

}

private void startUpdateTask() {
    this.timer = new Timer() {

        @Override
        public void run() {
            GWTMemoryIssue.this.getTableData();

        }
    };
    this.timer.scheduleRepeating(2000);
}

public void loadTable() {
    Runnable onLoadCallback = new Runnable() {
        public void run() {
            GWTMemoryIssue.this.table = new Table(createTableData(), createTableOptions());
            GWTMemoryIssue.this.table.setSize("100%", "100%");
            GWTMemoryIssue.this.panel.add(GWTMemoryIssue.this.table);
            GWTMemoryIssue.this.startUpdateTask();
        }
    };

    VisualizationUtils.loadVisualizationApi(onLoadCallback, Table.PACKAGE);
}

private Options createTableOptions() {
    Options options = Options.create();

    return options;
}

private DataTable createTableData() {
    DataTable data = DataTable.create();

    data.addColumn(ColumnType.STRING, "Name");
    data.addColumn(ColumnType.NUMBER, "Intval 1");
    data.addColumn(ColumnType.NUMBER, "Intval 2");
    data.addColumn(ColumnType.NUMBER, "Intval 3");

    return data;
}

private void getTableData() {
    rpcService.getListOfItems(new AsyncCallback<ArrayList<ListItem>>(){
        public void onFailure(Throwable caught) {
            // Do nothing
        }

        public void onSuccess(ArrayList<ListItem> result) {
            if (WITH_TABLE){
                GWTMemoryIssue.this.updateTableData(result);
            }else{
                //Ignore the data from the server
            }
        }
    });
}

private void updateTableData(ArrayList<ListItem> result) {
    DataTable data = createTableData();

    data.addRows(result.size());

    int row = 0;
    for (ListItem li : result) {
        data.setValue(row, 0, li.getName());
        data.setValue(row, 1, li.getIntVal());
        data.setValue(row, 2, li.getIntSecondVal());
        data.setValue(row, 3, li.getThirdIntVal());
        row++;
    }

    this.table.draw(data, createTableOptions());
}
}

解决方案

With all the additional information you provided here are some thoughts. I guess the memory increase is caused by the lists remaining in memory. It's either possible the memory is not freed at all or the JavaScript garbage collector doesn't get time to clean up, due too the short time frame between updates. Here are some test you could do:

  1. To test if the garbage collector doesn't get time adapt you code such that the update only runs a finite number of times, and then check if the memory usage decreases over a few minutes. If the memory usage decreases, than it might be less of an issue in you real world example. But simple test it by setting the delay to the 30 seconds.
  2. You could help the garbage collector by clearing the list after they are used: I don't know what works best, so here are some suggestions: Remove object from the list, or loop over the list and set values to null. This should not be necessary in normal case, because the garbage collector would do it.

You can also try the following Firefox Memory profiler add-on to see if you can locate the memory increases: http://ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on

这篇关于内存使用GWT应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆