[md5] Обеспечить быструю обработку.

Тема в разделе "WASM.BEGINNERS", создана пользователем devillsd, 30 май 2010.

  1. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Нужно посчитать md5 для файлов больше 1 гб. На данный момент всё проиходит через буфер, а это: создать буфер ~ 1 минута, скопировать в буфер 1 минута, посчитать ~40 секунд(это для 1 гб). В итоге видим, что в 3-ри раза больше времени уходит на подготовку файла. Я бы и дальше думал что так и надо, но меня удивляет скорость загрузки HEX редакторов, этот же 1 гб, грузиться мгновенно. Выслушаю все советы, ниже куски моих баго-версий(VS C++, сам алгоритм md5 не вылаживаю, он слишком большой, и его скорость меня устраивает.):


    Код (Text):
    1. int main(int argc, _TCHAR* argv[])
    2. {
    3.     struct  stat    st;
    4.     char*   pchGRF;
    5.     unsigned char md5[0x020];
    6.     char* buffer[0x100];
    7.     FILE* file;
    8.         CFile file2;
    9.         CFileException FileException;
    10.     //Проверим наличие параметров
    11.     if(argc<2){
    12.         printf("Error! Use: <Path to GRF>\n");
    13.         exit(0);
    14.     }
    15.     //Сначала подготовим буфер.
    16.     if(!stat((const char*)argv[1],&st)){    //Если удалось прочитать файл
    17.         if(pchGRFList=(char*)malloc(st.st_size))    //Создаём буфер для данных
    18.             printf("Debug: Buffer created. Size: %d Byte.\n",st.st_size);
    19.         else
    20.             printf("Error! Buffer not created!\n");
    21.     }
    22.     else
    23.         printf("Error! Could not find file: '%s'\n",(char*)argv[1]);
    24.         //v.1
    25.     //Теперь грузим.
    26.        fopen_s(&file, (const char*)argv[2], "wb");
    27.        fgets(pchGRFList,st.st_size,file);
    28.       MD5(pchGRFList,st.st_size,md5);
    29.       //v.2
    30.      //wcListPath = new wchar_t[0x80];
    31.     //MultiByteToWideChar(CP_ACP, 0, argv[1], strlen(argv[1])+1, wcListPath, strlen(argv[1])+1);
    32.         //file2.open(wcListPath,CFile::modeRead,FileException);
    33.         //file.read(pchGRFList,st.st_size);
    34.         //MD5(pchGRFList,st.st_size,md5);
    35.     return 0;
    36. }
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Грузится только часть, не целиком.

    Вы создаёте буфер размером более гигабайта? Зачем? Создавайте и читайте к примеру по мегабайту.
     
  3. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Не знаю как перестроить md5 алгоритм под работу с кусками...

    Возможно ли работать напрямую с файлом, без записи в буфер?
     
  4. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    devillsd
    А чего там переделывать-то? Он же по определению потоковый. Могу показать свой велосипед на C++.

    Как вы себе это представляете? mmap тоже не лучшее решение в данном случае.
     
  5. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Пока месть, наткнулся на mmap, почему нелогично использовать в моём случае?? На "Велосипед" посмотрю с удовольствием. qwentet@gmail.com / 471-010-9 девять 0.
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Использование mmap здесь просто не оправдано.
     
  7. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Я очень рад вашей помощи, но хотелось бы услышать аргументы по поводу mmap.
    Пока гляну сорс.
     
  8. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Чёт не нашел опции - редактировать. Я так понимаю, этот класс работает так, начинаем с какого то буфера, а потом с каждым новым куском дынных производим операцию Update? Потом End, ну и получаем hash...
    Я всё правильно понял?
    И ещё , что за компилятор вы используете?
     
  9. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    mmap здесь тупо ничего не даст. Ни удобства(из-за интерпретации как памяти), ни скорости(так как скорее всего файл не будет до этого промаплен). Оно может дать только тормоза, из-за большого расхода памяти и свопа. Так что не нужно.
     
  10. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Да, примерно так.
    Код (Text):
    1. MD5 hash;
    2. hash.Begin();
    3. hash.Update(...);
    4. hash.Update(...);
    5. ....
    6. hash.End();
    7. hash.GetHash(...);
    Компилятор gcc, но должно работать на любом.
     
  11. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    А ещё добавлю=) Так как имеем потоковый md5, то прекрасно справимся с подзагрузкой в буфер...
    Спасибо за код, щяз буду тестить. Всё же, какой компилятор используете?
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Про компилятор понял, попробуйте лучше это. ^). Здесь кроссплатформенно.
     
  13. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Booster
    СПАСИБО!
    Код работает ПРЕВОСХОДНО! ОГРОМНОЕ СПАСИБО!
     
  14. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    devillsd
    За какое время теперь вычисляется?
     
  15. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Если Вы ещё здесь, то очень кстати!
    Теперь имею, очень большую скорость считывания MD5, НОО!! С файлами более 1 GB ( может и на меньших размерах, на файлах около 70 mb всё ОК) трабл, просчитывает неверный Hash.
    С чем это может быть связано?
    Код (Text):
    1. CFile pFile;
    2.     CFileException pFileException;
    3.     //struct stat st;
    4.     //wchar_t wcFilePath[0x080];
    5.     unsigned char* chFileBuff;
    6.     int cDataSize;
    7.     MD5 md5calc;
    8.     char md5[0x010];
    9.     unsigned long RoundDataSize=ROUND_DATA_SIZE;
    10.     //int CurCarret;
    11.     if(argc<2){
    12.         printf("Error! Use: <Path to GRF List> <Path to GRF DB>\n");
    13.         exit(0);
    14.     }
    15.  
    16.     //MultiByteToWideChar(CP_ACP, 0, argv[1], strlen(argv[1])+1, wcFilePath, strlen(argv[1])+1);
    17.     if(!pFile.Open((char*)argv[1], CFile::modeRead, &pFileException)){
    18.         switch(pFileException.m_cause){
    19.             case 2:
    20.                 printf("Error: File not found!");
    21.                 break;
    22.             case 3:
    23.                 printf("Error: Bad path!");
    24.                 break;
    25.             default:
    26.                 printf("Error: ?");
    27.                 break;
    28.         }
    29.         exit(0);
    30.     }
    31.     //инициализируем алгоритм MD5
    32.     md5calc.Begin();
    33.     //Создадим буфер
    34.     if(pFile.GetLength()<ROUND_DATA_SIZE)
    35.         RoundDataSize = pFile.GetLength();
    36.     chFileBuff = (unsigned char*)malloc(RoundDataSize);
    37.     while(cDataSize=pFile.Read(chFileBuff, RoundDataSize)){
    38.         if(cDataSize!=ROUND_DATA_SIZE)
    39.             printf("Near the end");
    40.         md5calc.Update((char*)chFileBuff, cDataSize);
    41.     }
    42.     md5calc.End();
    43.     md5calc.GetHash(md5);
    44.     free(chFileBuff);
    45.     pFile.Close();
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    У меня всё корректно, тестирую 4Гб файлы.
    Как проверяете корректность? Бинарный режим открытия файла не забыли?
    Тестовый код.
    Код (Text):
    1. #include "Md5.hpp"
    2. #include <fstream>
    3. #include <iostream>
    4.  
    5. char* itoa(int value, char* result, int base);
    6.  
    7. int main (int argc, char* argv[])
    8. {
    9.     if (argc<2)
    10.         return 1;
    11.     char buf[0xffff];
    12.     std::ifstream ifs(argv[1], std::ios::binary);
    13.     if (!ifs.is_open())
    14.         return 1;
    15.     MD5 hash;
    16.     hash.Begin();
    17.     std::streamsize size = 1;
    18.     while(size)
    19.     {
    20.         size = ifs.readsome(buf, sizeof(buf));
    21.         hash.Update(buf, size);
    22.     }
    23.     hash.End();
    24.     char szStr[33];
    25.     szStr[32] = 0;
    26.     for (int i=0; i<16; i++)
    27.     {
    28.         szStr[i*2]='0';
    29.         szStr[i*2+1]='0';
    30.         itoa(hash.GetHash()[i],&szStr[i*2], 16);
    31.     }
    32.     std::cout<<szStr<<std::endl;
    33. }
    34.  
    35. /**
    36.          * C++ version 0.4 char* style "itoa":
    37.          * Written by Lukás Chmela
    38.          * Released under GPLv3.
    39.          */
    40. char* itoa(int value, char* result, int base) {
    41.     // check that the base if valid
    42.     if (base < 2 || base > 36) { *result = '\0'; return result; }
    43.  
    44.     char* ptr = result, *ptr1 = result, tmp_char;
    45.     int tmp_value;
    46.  
    47.     do {
    48.         tmp_value = value;
    49.         value /= base;
    50.         *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
    51.     } while ( value );
    52.  
    53.     // Apply negative sign
    54.     if (tmp_value < 0) *ptr++ = '-';
    55.     //*ptr-- = '\0';
    56.     --ptr;
    57.     while(ptr1 < ptr) {
    58.         tmp_char = *ptr;
    59.         *ptr--= *ptr1;
    60.         *ptr1++ = tmp_char;
    61.     }
    62.     return result;
    63. }
    В качестве аргумента передаёте имя файла, оно считает и показывает хеш. Для проверки можно использовать md5sum, которая есть и для никсов и для винды.
     
  17. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Там есть ошибка, цикл нужен такой.
    Код (Text):
    1. for (int i=0; i<16; i++)
    2.         {
    3.                 szStr[i*2]=0;
    4.                 szStr[i*2+1]=0;
    5.                 itoa(hash.GetHash()[i],&szStr[i*2], 16);
    6.                 if (szStr[i*2+1]==0)
    7.                 {
    8.                         szStr[i*2+1] = szStr[i*2];
    9.                         szStr[i*2] = '0';
    10.                 }
    11.         }
     
  18. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    Корректность проверяю посредством TotalCommander, в нём есть функция подсчёта md5, действительно не учёл typeBinary, но после исправления ошибки баг не пропал...
    Попробую применить Ваш код, но бесит, в чём же проблема моего кода?
     
  19. devillsd

    devillsd New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2008
    Сообщения:
    131
    .redsome отказывается считывать данные из файла!
    Пытался даже скопировать Ваш не внося изменений, в итоге readsome возвращаёт - 0!
     
  20. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    на любом файле?