سؤال

أنا أعمل حاليا على GWT التطبيق كدليل على التكنولوجيا للمشاريع المستقبلية.أنا أحب طريقة بناء بلدي اياكس البرمجية في جافا بدلا من جافا سكريبت.ولكن يبدو لي أن تكون قيد التشغيل في الذاكرة مشكلة عند تكرار المكالمات إلى خدمة RPC.المتصفح استخدام الذاكرة يستمر في النمو.

عند البحث جوجل أستمر في القراءة حول كيفية كبيرة GWT هو أن من المستحيل الحصول على تسرب الذاكرة بحيث يمكن لأي شخص أن يشرح لماذا المتصفح (فايرفوكس والكروم) الذاكرة بالصواريخ?

شكرا مقدما على مساعدتي ، برام

رمز:

...

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);
  }
}

تحرير:

لقد قضيت بعض الوقت لكتابة اختبار التطبيقات التي يمكن تحميلها هنا.ركضت التطبيق لمدة نصف ساعة تقريبا مع تحديث الجدول تمكين بعد أن فايرفوكس استغرق حوالي 350 ميغابايت من الذاكرة.ركضت أيضا اختبار مع تحديث جدول تعطيل لمدة ساعة استخدام الذاكرة في فايرفوكس ذهب إلى أكثر من 100MB.

(لتشغيل هذه العينة تحتاج التصور جوجل API GWT التي يمكن تحميلها من جوجل ولكن أنا لا يسمح بنشر رابط من سياسة المستخدم )

أنا فقط حصلت على المنزل من العمل والبدء في اختبار آخر دون بيانات الجدول تحديث لمعرفة ما إذا كان يحتفظ زيادة استخدام الذاكرة أو إذا كان يتوقف عند نقطة معينة.

هذا هو العميل تنفيذ الطبقة (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());
}
}
هل كانت مفيدة؟

المحلول

مع جميع المعلومات الإضافية التي قدمتها وهنا بعض الأفكار.أعتقد أن الذاكرة الزيادة الناجمة عن القوائم المتبقية في الذاكرة.إما ممكنة من الذاكرة لا تتحرر في كل أو جافا سكريبت جامع القمامة لا تحصل على الوقت لتنظيف ، ويرجع ذلك أيضا الإطار الزمني القصير بين التحديثات.وهنا بعض التجارب يمكن أن تفعل:

  1. لاختبار إذا جامع القمامة لا تحصل على الوقت التكيف أنت رمز هذه أن التحديث يعمل فقط عدد محدود من مرات ثم تحقق إذا كان استخدام الذاكرة تنخفض أكثر من بضع دقائق.إذا كان استخدام الذاكرة النقصان ، مما قد يكون أقل من قضية في العالم الحقيقي سبيل المثال.ولكن اختبار بسيط بوضع التأخير إلى 30 ثانية.
  2. هل يمكن أن تساعد على جمع القمامة عن طريق مسح قائمة بعد استخدامها:أنا لا أعرف ما يعمل بشكل أفضل, لذلك إليك بعض الاقتراحات:إزالة الكائن من القائمة ، أو حلقة أكثر من قائمة وتعيين القيم null.هذا لا ينبغي أن يكون من الضروري في حالة طبيعية ، لأن جمع القمامة قد تفعل ذلك.

يمكنك أيضا محاولة التالية فايرفوكس الذاكرة التعريف إضافة إلى انظر إذا كان يمكنك العثور على زيادة الذاكرة: http://ajaxian.com/archives/enhanced-firefox-memory-profiler-add-on

نصائح أخرى

لقد تم استخدام GWT بعض الوقت مع العديد من الجداول RPCs و حتى الآن أكثر تسرب الذاكرة وجدت كانت غلطتي.

RPC طبقة لا يبدو أن تسرب بقدر ما أعرف و المثال الخاص بك هو بسيط جدا أن يطرح مشكلة.

قد تحتاج إلى إلقاء نظرة على ما updateTable الأسلوب يقوم به في الواقع ، قد يكون لديك تسرب في التعليمات البرمجية الخاصة بك.

الشيء الوحيد الذي يمكن أن يسبب ضخمة تسرب الذاكرة مع GWT هي Imagebundles في IE.فمن المعروف أن هذه تسرب للغاية في GWT لأنها تستخدم DXTransform لدعم الشفافية ألفا.الذاكرة ترتفع في أجزاء كبيرة في كل مرة الحاجيات على الشاشة.ولكن هناك الحيل لتجنب هذا.

لا يوجد أي صريح العملية اللازمة لتنظيف القمامة في جافا سكريبت.ومن المفترض أن يتم تشغيلها تلقائيا (على الرغم من أن GC في المتصفح ليست على نفس المستوى كما في حديث JVM).

GWT هل من الأفضل تجنب الأخطاء الشائعة التي قد تتسبب في تسرب الذاكرة في JS (المراجع الدائرية بين شبيبة و DOM بشدة التعامل مع بعض المتصفحات).

لذا فإن السؤال هو:هو استخدام الذاكرة دائما ؟ أو أنها أعلى في نقطة معينة (أو أنها مجرد حوادث مع بعض من الذاكرة؟).يمكن أن يكون من الطبيعي أن التطبيق الخاص بك يبدو أن النمو...ولكن GC أن ركلة في بعض نقطة.

في تطبيق استخدام الذاكرة يتصدر بها في حوالي 64 ميغابايت.ولكن أنا لا أعمل على أوبونتو ، أي على ويندوز هو هدفنا الرئيسي ، على الرغم من أنني في بعض الأحيان اختبار على فايرفوكس وكذلك (و هناك لا أرى تسرب إما).

شيء آخر قد تحتاج إلى القيام به هو تجنب الاقتراع كل 2 ثانية مثلك.إذا طلب وقتا أطول من 2 ثانية تبدأ كينج تصل الطلبات (متصفح لديه قيود على عدد الاتصالات المتزامنة).لذا فإنه من الأفضل أن تنتظر الرد قبل إطلاق جهاز توقيت جديد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top