Как я могу ускорить мой анализатор текстовых файлов Java? - PullRequest
1 голос
/ 02 октября 2011

Я читаю около 600 текстовых файлов, а затем анализирую каждый файл по отдельности и добавляю все термины на карту, чтобы узнать частоту каждого слова в 600 файлах.(около 400 МБ).

Мои функции синтаксического анализатора включают в себя следующие шаги (упорядочены):

  • поиск текста между двумя тегами, который является соответствующим текстом для чтения в каждом файле.
  • нижний регистр всего текста
  • string.split с несколькими разделителями.
  • создание arrayList со словами вроде этого: "aaa-aa", затем добавление к строке, разделенной выше, идисконтирование "aaa" и "aa" в строку [].(Я сделал это, потому что хотел, чтобы «-» был разделителем, но я также хотел, чтобы «ааа-аа» было только одним словом, а не «ааа» и «аа».
  • get String [] и сопоставление с картой = новая HashMap ... (слово, частота)
  • печать всего.

У меня уходит около 8 минут и 48 секунд в двухъядерном процессоре2,2 ГГц, 2 ГБ ОЗУ. Я хотел бы получить совет о том, как ускорить этот процесс. Должен ли я ожидать, что он будет таким медленным? И, если возможно, как я могу узнать (в сетевых компонентах), какие функции занимают больше времени для выполнения?

найдено уникальных слов: 398752.

КОД:

File file = new File(dir);
String[] files = file.list();

for (int i = 0; i < files.length; i++) {
    BufferedReader br = new BufferedReader(
        new InputStreamReader(
            new BufferedInputStream(
                new FileInputStream(dir + files[i])), encoding));
    try {
        String line;
        while ((line = br.readLine()) != null) {
            parsedString = parseString(line); // parse the string
            m = stringToMap(parsedString, m);
        }
    } finally {
        br.close();
    }
}

РЕДАКТИРОВАТЬ: Проверьте это:

! [Введите описание изображенияздесь] [1]

Я не знаю, что сделать.


РЕДАКТИРОВАТЬ: 80% ВРЕМЕНИ, ИСПОЛЬЗУЕМОЙ С ЭТОЙ ФУНКЦИЕЙ

    public String [] parseString(String sentence){
         // separators; ,:;'"\/<>()[]*~^ºª+&%$ etc..
        String[] parts = sentence.toLowerCase().split("[,\\s\\-:\\?\\!\\«\\»\\'\\´\\`\\\"\\.\\\\\\/()<>*º;+&ª%\\[\\]~^]");

        Map<String, String> o = new HashMap<String, String>(); // save the hyphened words, aaa-bbb like Map<aaa,bbb>

        Pattern pattern = Pattern.compile("(?<![A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû-])[A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû]+-[A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû]+(?![A-Za-z-])");
        Matcher matcher = pattern.matcher(sentence);

    // Find all matches like this: ("aaa-bb or bbb-cc") and put it to map to later add this words to the original map and discount the single words "aaa-aa" like "aaa" and "aa"
        for(int i=0; matcher.find(); i++){
           String [] tempo = matcher.group().split("-");
           o.put(tempo[0], tempo[1]);
        }
        //System.out.println("words: " + o);


        ArrayList temp = new ArrayList();
        temp.addAll(Arrays.asList(parts));

        for (Map.Entry<String, String> entry : o.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            temp.add(key+"-"+value);
            if(temp.indexOf(key)!=-1){
                temp.remove(temp.indexOf(key));
            }
            if(temp.indexOf(value)!=-1){
                temp.remove(temp.indexOf(value));
            }
        }


        String []strArray = new String[temp.size()];
        temp.toArray(strArray);
                return strArray;

  }

600 файлов,каждый файл размером около 0,5 МБ

EDIT3 # - шаблон больше не компилируется при каждом чтении строки. Новые изображения:

enter image description here

2 : enter image description here

Ответы [ 8 ]

3 голосов
/ 02 октября 2011

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

Части вашего кода, которые могут оказать наибольшее влияние на производительность, - это те, которые выполняются чаще всего - это те части, которые вы не показывали.

Обновление после скриншота памяти

Посмотрите на все эти объекты Pattern $ 6 на скриншоте. Я думаю, вы много перекомпилируете шаблон - возможно, для каждой строки. Это заняло бы много времени.

Обновление 2 - после добавления кода к вопросу.

Yup - два шаблона, скомпилированных в каждой строке - явный, а также "-" в разбиении (конечно, намного дешевле). Хотелось бы, чтобы они не добавляли split () в String без использования скомпилированного шаблона в качестве аргумента. Я вижу некоторые другие вещи, которые можно улучшить, но больше ничего, как большая компиляция. Просто скомпилируйте шаблон один раз, вне этой функции, возможно, как статический член класса.

1 голос
/ 02 октября 2011

Ничто в коде, который вы нам показали, не является очевидным источником проблем с производительностью. Проблема, скорее всего, связана с тем, как вы анализируете строки или извлекаете слова и помещаете их в карту. Если вам нужны дополнительные советы, вам нужно опубликовать код для этих методов и код, который объявляет / инициализирует карту.

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

@ Совет Эда Стауба также звучит. Запуск приложения с кучей, которая слишком мала может привести к серьезным проблемам с производительностью.

1 голос
/ 02 октября 2011

Запустите код через профилировщик Netbeans и выясните, где он занимает больше всего времени (щелкните правой кнопкой мыши проект и выберите профиль, убедитесь, что вы используете время, а не память).

1 голос
/ 02 октября 2011

Это просто разбор, который занимает так много времени, или чтение файла тоже?

Что касается чтения файлов, вы, вероятно, можете ускорить его, читая файлы в нескольких потоках. Но первый шаг - выяснить, все ли время занимает чтение или анализ, чтобы вы могли решить нужную проблему.

1 голос
/ 02 октября 2011

Попробуйте использовать одно регулярное выражение, в котором есть группа, соответствующая каждому слову, содержащемуся в тегах, - чтобы одно целое регулярное выражение могло использоваться для всего вашего ввода, и не было бы отдельной «разделенной» стадии.В противном случае ваш подход кажется разумным, хотя я не понимаю, что вы подразумеваете под «получить строку [] ...» - я думал, что вы используете ArrayList.В любом случае постарайтесь свести к минимуму создание объектов как для стоимости строительства, так и для сбора мусора.

1 голос
/ 02 октября 2011

Если вы этого еще не сделали, используйте BufferedInputStream и BufferedReader для чтения файлов.Подобная двойная буферизация заметно лучше, чем использование только BufferedInputStream или BufferedReader.Например:

BufferedReader rdr = new BufferedReader(
    new InputStreamReader(
        new BufferedInputStream(
            new FileInputStream(aFile)
        )
        /* add an encoding arg here (e.g., ', "UTF-8"') if appropriate */
    )
);

Если вы разместите соответствующие части своего кода, у нас будет шанс прокомментировать, как улучшить обработку.

РЕДАКТИРОВАТЬ:

Основываясь на ваших изменениях, вот пара предложений:

  1. Компилируйте шаблон один раз и сохраняйте его как статическую переменную, а не компилируйте каждый раз, когда вы вызываете parseString.
  2. Сохраните значения temp.indexOf(key) и temp.indexOf(value) при первом вызове, а затем используйте сохраненные значения вместо вызова indexOf во второй раз.
0 голосов
/ 02 октября 2011

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

0 голосов
/ 02 октября 2011

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

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

...