2016-06-14 2 views
2

У меня проблема с огромными вложенными структурами данных (от JSON Spirit). Во время отладки, когда эта структура заполнена данными, Eclipse начинает работать очень медленно, после каждого шага он ожидает распечатки данных из GDB. Дело в том, что Eclipse собирает много информации о локальных переменных, даже когда я не расширяю эту структуру данных. Когда прекрасная печать отключена, она работает, но, конечно, я ничего не вижу внутри контейнеров STL.Eclipse CDT (4.5.1) работает медленно с красивой печатью

Я использую принтеры из GDB SVN

Вот маленький кусочек кода, который может сделать аналогичные проблемы:

#include <iostream> 
#include <string> 
#include <map> 

int main() { 
    std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> mega_map; 

    const int factor = 50; 
    for (int c = 0; c < factor; ++c){ 
     std::map<std::string, std::map<std::string, std::string>> b_map; 
     for (int b = 0; b < factor; ++b){ 
      std::map<std::string, std::string> a_map; 
      for (int a = 0; a < factor; ++a){ 
       std::string a_str = "a"; 
       a_str += (std::to_string(a)); 
       auto a_pair = std::make_pair("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + a_str, "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"); 
       a_map.insert(a_pair); 
      } 
      std::string b_str = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; 
      b_str += (std::to_string(b)); 
      b_map[b_str] = a_map; 
     } 
     std::string c_str = "cccccccccccccccccccccccccccccccccccccccc"; 
     c_str += (std::to_string(c)); 
     mega_map[c_str] = b_map; 
    } 
    return 0; 
} 

Просто сделайте тормоз в «возвращении», и вы увидите, что он принимает много времени, чтобы получить что-то в окне «Переменные». За это время вы не можете отлаживать.

В GDB set print elements number-of-elements есть флаг, который может ограничить количество элементов в контейнерах для печати, но работает, но пока меня не интересуют эти вложенные структуры, эти параметры влияют на другие контейнеры, которые я бы хотел проверить.

Любые идеи, как исправить это?

Спасибо.

ответ

0

Мы (коллеги и я) сегодня столкнулись и исследовали этот вопрос, и вот наш вывод. К сожалению, мы не нашли способ решить эту проблему, используя только некоторые настройки, но обнаружили некоторые изменения в CDT и GDB, которые могли бы облегчить ее. Если вы можете создать свой собственный CDT или GDB, это может вам помочь.

CDT спрашивает GDB для местных жителей, используя -stack-list-locals, с аргументом, чтобы получить их значения. Для довольно отпечатанного контейнера, GDB заканчивается в том числе детей:

std::vector of length 20, capacity 20 = {<children here>} 

Для вложенных структур данных, это может в конечном итоге огромное. Одно из исправлений заключается в том, чтобы заставить CDT не запрашивать эти значения. Он будет правильно использовать переменные объекты и запрашивать значения по мере необходимости, когда вы расширяете структуры данных. Вот разница:

diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java 
index c319eb8..23bbb8a 100644 
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java 
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java 
@@ -859,7 +859,7 @@ implements IStack, ICachingService { 
      fMICommandCache.execute(
        // Don't ask for value when we are visualizing trace data, since some 
        // data will not be there, and the command will fail 
-     fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), 
+     fCommandFactory.createMIStackListLocals(frameDmc, false), 
        new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), rm) { 
         @Override 
         protected void handleSuccess() { 
@@ -988,7 +988,7 @@ implements IStack, ICachingService { 
       // the result without the values 
       // Don't ask for value when we are visualizing trace data, since some 
       // data will not be there, and the command will fail 
-    fCommandFactory.createMIStackListLocals(frameDmc, !fTraceVisualization), 
+    fCommandFactory.createMIStackListLocals(frameDmc, false), 
       new DataRequestMonitor<MIStackListLocalsInfo>(getExecutor(), countingRm) { 
        @Override 
        protected void handleSuccess() { 

Есть и другие случаи, когда CDT будет выдавать запросы, которые делают GDB выплюнуть всю рекурсивную структуру данных, то есть, если у вас есть переменная, выбранная в переменных просмотра или при наведении его. Затем вы увидите полное расширенное значение в разделе «Подробности». Но если у вас нет этой переменной, выбранной при шаге, она быстро срабатывает.

Возможное исправление в GDB состоит в том, чтобы не рекурсивно выводить из него печатные структуры данных. Этот хак, например, ограничивает их на один уровень детей:

diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c 
index 66929bf..b213699 100644 
--- a/gdb/python/py-prettyprint.c 
+++ b/gdb/python/py-prettyprint.c 
@@ -700,7 +700,7 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang, 
    /* Print the section */ 
    print_result = print_string_repr (printer.get(), hint.get(), stream, 
        recurse, options, language, gdbarch); 
- if (print_result != string_repr_error) 
+ if (print_result != string_repr_error && recurse == 0) 
    print_children (printer.get(), hint.get(), stream, recurse, options, 
      language, print_result == string_repr_none); 

А вклад в вышестоящие GDB можно считать, где этот предел рекурсии является настройка с reasonnable значением.

+0

Это похоже на https://bugs.eclipse.org/bugs/show_bug.cgi?id=519561, и я ценю анализ, который вы сделали. Можете ли вы добавить те же детали к ошибке, особенно если вы считаете, что это то же самое. Благодаря! –