Проблема производительности Java: необходимо выполнить итерацию более 8 миллионов записей с проверкой целевой ветви - PullRequest
0 голосов
/ 01 мая 2019

У нас есть система, которая обрабатывает плоский файл и (с несколькими проверками только) вставляет в базу данных.

Этот код:

//There can be 8 million lines-of-codes

for(String line: lines){
   if (!Class.isBranchNoValid(validBranchNoArr, obj.branchNo)){
    continue;
   }
   list.add(line);
 }

определение isBranchNoValid:

//the array length ranges from 2 to 5 only

public static boolean isBranchNoValid(String[] validBranchNoArr, String branchNo) {
  for (int i = 0; i < validBranchNoArr.length; i++) {
    if (validBranchNoArr[i].equals(branchNo)) {
        return true;
      }
       }
    return false;
    } 

Проверка выполняется на уровне строки (мы должны отфильтровать или пропустить строку, у которой нет branchNo в массиве). Ранее это не было (фильтровать) дело.

Теперь ухудшение производительности беспокоит нас. Я понимаю (может быть, я ошибаюсь), что этот повторный вызов функции вызывает многократное создание stack, что приводит к очень высокому вызову GC.

Я не могу найти способ (возможно ли даже) выполнить этот фильтр без высокой стоимости снижения производительности (небольшая разница в порядке).

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Таким образом, в вашем сценарии есть несколько возможных узких мест.

  1. чтение строк файла
  2. Анализ строки для построения объекта для вставки в базу данных
  3. проверить применимость объекта (т.е. ответвления без фильтра)
  4. вставить в db

Как правило, вы бы сказали, что IO - самый медленный, поэтому 1. и 2.Вы говорите ничего, кроме 2. изменилось, верно?Это странно.

В любом случае, если вы хотите оптимизировать это, я бы не передавал массив около 8 миллионов раз, и я бы тоже не повторял его каждый раз.Так как ваши действительные ветви известны, создайте HashSet из него - он имеет доступ O (1).

Set<String> validBranches = Arrays.stream(branches)
                              .collect(Collectors.toCollection(HashSet::new));

Затем выполните итерации строк

for (String line : lines) {
    YourObject obj = parse(line);
    if (validBranches.contains(obj.branchNo)) {
        writeToDb(obj);
    }
}

или, впотоковая версия

Files.lines(yourPath)
     .map(this::parse)
     .filter(o -> validBranches.contains(o.branchNo))
     .forEach(this::writeToDb);

Я бы также проверил, не эффективнее ли сначала собрать пакет объектов, а затем записать в базу данных.Кроме того, возможно, что параллельная обработка строк увеличивает скорость, если синтаксический анализ требует много времени.

0 голосов
/ 01 мая 2019

Это точно не проблема стека, потому что ваша функция не рекурсивная, ничего не хранится в стеке между вызовами; после каждого вызова переменные стираются, так как они больше не нужны.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...