Сравнение записей в файле и статистика отчетов - Сценарий 1 - PullRequest
1 голос
/ 21 мая 2009

Требования:

Факт 1: у нас есть несколько файлов данных, созданных устаревшей системой

Факт 2: У нас есть несколько файлов данных, созданных новой системой, которые в конечном итоге должны заменить устаревшую

Факт 3:

  1. Оба файла являются текстовыми / ASCII файлами, с записями, состоящими из несколько строк.
  2. Каждая строка в записи состоит имени поля и значения поля.
  3. Формат, в котором строки представлены разные между 1 и 2, но имя поля и значение поля можно извлечь из каждой строки с помощью регулярных выражений
  4. Имена полей могут изменяться от 1 до 2, но у нас есть отображение, которое связывает их
  5. Каждая запись имеет уникальный идентификатор это помогает нам связать наследие запись с новой записью в качестве заказа записей в выходной файл нужно не должно быть одинаковым в обеих системах.
  6. Каждый файл для сравнения является минимумом 10 МБ в среднем случае 30 - 35 MB

Факт 4: Как и когда мы выполняем итерацию при создании новой системы, нам необходимо сравнить файлы, созданные обеими системами в одинаковых условиях, и согласовать различия.

Факт 5: Это сравнение выполняется вручную с использованием дорогого инструмента визуального сравнения. Чтобы помочь в этом, я написал инструмент, который объединяет два разных имени поля в общее имя, а затем сортирует имена полей в каждой записи, в каждом файле, чтобы они синхронизировались по порядку (новые файлы могут иметь дополнительные поля, которые игнорируются в визуальная разница)

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

Очевидно, вопрос в том, какими должны быть 'ALG' и 'DS'?

Сценарий, к которому я должен обратиться:

Там, где люди продолжают визуально проверять различия - при этом производительность ожидающего скрипта неутешительна - большая часть обработки заключается в сортировке массива строк в лексикографическом порядке (чтение / выборка элемента массива: Tie :: File :: FETCH, Tie :: File :: Cache :: lookup и помещаем его в правильное место для сортировки: Tie :: File :: Cache :: insert, Tie :: File :: Heap :: insert)

use strict;
use warnings;

use Tie::File;

use Data::Dumper;

use Digest::MD5 qw(md5_hex);

# open an existing file in read-only mode
use Fcntl 'O_RDONLY';

die "Usage: $0 <unsorted input filename> <sorted output filename>" if ($#ARGV < 1);

our $recordsWrittenCount = 0;
our $fieldsSorted = 0;

our @array;

tie @array, 'Tie::File', $ARGV[0], memory => 50_000_000, mode => O_RDONLY or die "Cannot open $ARGV[0]: $!";

open(OUTFILE, ">" .  $ARGV[1]) or die "Cannot open $ARGV[1]: $!";

our @tempRecordStorage = ();

our $dx = 0;

# Now read in the EL6 file

our $numberOfLines = @array; # accessing @array in a loop might be expensive as it is tied?? 

for($dx = 0; $dx < $numberOfLines; ++$dx)
{
    if($array[$dx] eq 'RECORD')
    {
        ++$recordsWrittenCount;

        my $endOfRecord = $dx;

        until($array[++$endOfRecord] eq '.')
        {
            push @tempRecordStorage, $array[$endOfRecord];
            ++$fieldsSorted;
        }

        print OUTFILE "RECORD\n";

        local $, = "\n";
        print OUTFILE sort @tempRecordStorage;
        @tempRecordStorage = ();

        print OUTFILE "\n.\n"; # PERL does not postfix trailing separator after the last array element, so we need to do this ourselves)

        $dx = $endOfRecord;     
    }
}

close(OUTFILE);

# Display results to user

print "\n[*] Done: " . $fieldsSorted . " fields sorted from " . $recordsWrittenCount . " records written.\n";

Так что я подумал об этом, и я думаю, что-то вроде trie, может быть, trie / PATRICIA trie с суффиксом, так что при самой вставке поля в каждой записи сортируются. Следовательно, мне не пришлось бы сортировать окончательный массив всего за один раз, и стоимость была бы амортизирована (спекуляция с моей стороны)

В этом случае возникает еще одна проблема - Tie :: File использует массив для абстрагирования строк в файле - чтение строк в дерево и последующая их сериализация обратно в массив потребует дополнительной памяти И обработки /

Вопрос в том, будет ли это стоить больше, чем текущая стоимость сортировки связанного массива?

1 Ответ

2 голосов
/ 21 мая 2009

Tie :: File очень медленный. Для этого есть две причины: во-первых, связанные переменные значительно медленнее, чем стандартные переменные. Другая причина в том, что в случае Tie :: File данные в вашем массиве находятся на диске, а не в памяти. Это сильно замедляет доступ. Кеш Tie :: File может в некоторых случаях повысить производительность, но не тогда, когда вы просто зацикливаете массив по одному элементу за раз, как здесь. (Кэш помогает только при повторном посещении того же индекса.) Время использования Tie :: File - это когда у вас есть алгоритм, который требует наличия всех данных в памяти одновременно, но у вас недостаточно памяти для этого. Поскольку вы обрабатываете файл по одной строке за раз, используя Tie :: File, это не только бессмысленно, но и вредно.

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

%data = (
  id1 => {
    field1 => value1,
    field2 => value2,
  },
  id2 => {
    field1 => value1,
    field2 => value2,
  },
);

Если вы используете сопоставления для нормализации имен полей при построении структуры данных, это упростит сравнение.

Для сравнения данных сделайте следующее:

  1. Выполнить сравнение набора ключей двух хешей. Это должно создать три списка: идентификаторы, присутствующие только в устаревших данных, идентификаторы, присутствующие только в новых данных, и идентификаторы, присутствующие в обоих.
  2. Сообщить о списках идентификаторов, которые появляются только в одном наборе данных. Это записи, которые не имеют соответствующей записи в другом наборе данных.
  3. Для идентификаторов в обоих наборах данных сравните данные для каждого поля идентификатора по полю и сообщите о любых различиях.
...