Сравнение записей в файле и статистика отчетов - Сценарий 1

Требования следующие:

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

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

Факт 3:

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

Факт 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 ответ

Решение

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. Для идентификаторов в обоих наборах данных сравните данные для каждого поля идентификатора по полю и сообщите о любых различиях.
Другие вопросы по тегам