| Посчитать хеш | 
|  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 19:53 | Сообщение # 1 |  | заслуженный участник Сейчас нет на сайте | Пишу DLL'ку для Game Maker Studio 2 которая будет считать хеш файла Adler32. Саму функцию написал правильно, всё работает, но скорость просто ужасная.
 
 Для сравнения есть файл 350мб:
 md5_file который есть в gms считает за ~2 секунды, функция которую написал я считает это больше 20 секунд.
 
 С C++ знаком очень плохо, поэтому прошу помощи, проверьте где и что не так.
 
 
 Код #include "stdafx.h"#include "MHash.h"
 #include <stdio.h>
 
 #define DLLEXPORT extern "C" __declspec(dllexport)
 
 DLLEXPORT double adler32_file(char* filename)
 {
 FILE *fid = fopen(filename, "rb");
 if (fid == NULL) return(0);
 
 unsigned char c;
 
 unsigned long s1 = 1;
 unsigned long s2 = 0;
 
 while(true) {
 c = fgetc(fid);
 
 if (feof(fid)) break;
 
 s1 = (s1 + c) % 65521;
 s2 = (s2 + s1) % 65521;
 }
 
 return (s2 << 16) + s1;
 }
 
 Сообщение отредактировал maksim1221232 - Среда, 27 Июня 2018, 01:21 |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 19:58 | Сообщение # 2 |  |   старожил Сейчас нет на сайте | maksim1221232, читать по одному байтику из файла - узкое место. Закачайте файл в буффер, потом из буффера читайте. |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 20:36 | Сообщение # 3 |  | заслуженный участник Сейчас нет на сайте | Как это можно сделать? 
 Нашел какой то кусок кода, переписал немного, но считает теперь не правильно.
 
 Код DLLEXPORT double adler32_file(char* filename){
 FILE * ptrFile = fopen(filename, "rb");
 
 if (ptrFile == NULL) return(-1);
 
 fseek(ptrFile, 0, SEEK_END);
 long lSize = ftell(ptrFile);
 rewind(ptrFile);
 
 char * buffer = (char*)malloc(sizeof(char) * lSize);
 if (buffer == NULL) return(-2);
 
 size_t result = fread(buffer, 1, lSize, ptrFile);
 if (result != lSize) return(-3);
 
 puts(buffer);
 
 int buffSize = strlen(buffer);
 unsigned long s1 = 1;
 unsigned long s2 = 0;
 
 for (int i = 0; i <= buffSize; i++) {
 s1 = (s1 + buffer[i]) % 65521;
 s2 = (s2 + s1) % 65521;
 }
 
 fclose(ptrFile);
 free(buffer);
 return (s2 << 16) + s1;
 }
 
 Сообщение отредактировал maksim1221232 - Воскресенье, 17 Июня 2018, 20:36 |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 20:43 | Сообщение # 4 |  |   старожил Сейчас нет на сайте | maksim1221232, 1. Уберите puts(buffer).
 2. strlen использовать нельзя. Берите величину lSize, которую Вы уже получили.
 3. <= buffSize - будет переполнение. Равно знак надо убрать.
 |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 21:00 | Сообщение # 5 |  | заслуженный участник Сейчас нет на сайте | Теперь считает правильно, но все ровно md5_file почему то быстрее... p.s md5 2 секунды, adler32 4 секунды.
 |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 21:08 | Сообщение # 6 |  |   старожил Сейчас нет на сайте | maksim1221232, попробуйте считывать не весь файл в буффер, а порциями, скажем по 1М - эксперементально выберете оптимальную величину буффера. |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 21:29 | Сообщение # 7 |  | заслуженный участник Сейчас нет на сайте | Код FILE * ptrFile = fopen(filename, "rb");
 if (ptrFile == NULL) return(-1);
 
 long pSize = (1024 * 1024 * 1024) * 16;
 
 unsigned char * buffer = (unsigned char*)malloc(sizeof(unsigned char) * pSize);
 if (buffer == NULL) return(-2);
 
 unsigned long s1 = 1;
 unsigned long s2 = 0;
 
 while (true) {
 size_t result = fread(buffer, 1, pSize, ptrFile);
 
 for (int i = 0; i < result; i++) {
 s1 = (s1 + buffer[i]) % 65521;
 s2 = (s2 + s1) % 65521;
 }
 
 if (feof(ptrFile)) break;
 }
 
 fclose(ptrFile);
 free(buffer);
 return (s2 << 16) + s1;
Теперь вообще не работает...
 
 
 Сообщение отредактировал maksim1221232 - Воскресенье, 17 Июня 2018, 21:29 |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 21:37 | Сообщение # 8 |  |   старожил Сейчас нет на сайте | maksim1221232, 
 1. ты запросил 16Г буффер. Великовато.
 2. if (feof(ptrFile)) break; не совсем корректно. Лучше когда размер прочитанного буффера не совпадает с запрашиваемым.
 
 То есть result ! = pSize break;
 |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 21:51 | Сообщение # 9 |  | заслуженный участник Сейчас нет на сайте | 3.4сек если читать по 700кб, ниже не нашел. |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 21:59 | Сообщение # 10 |  |   старожил Сейчас нет на сайте | maksim1221232, дальнейшая оптимизация: 
 % 65521 можно не каждый раз делать, а как только превысили эту цифру, то есть if > 65521 then % делать;
 
 
 Сообщение отредактировал falcoware - Воскресенье, 17 Июня 2018, 22:01 |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 22:18 | Сообщение # 11 |  | заслуженный участник Сейчас нет на сайте | Код DLLEXPORT double adler32_file(char* filename){
 FILE * ptrFile = fopen(filename, "rb");
 
 if (ptrFile == NULL) return(-1);
 
 const unsigned int pSize = 1024 * 128;
 
 unsigned char * buffer = (unsigned char*)malloc(pSize);
 if (buffer == NULL) return(-2);
 
 unsigned long s1 = 1, s2 = 0;
 
 size_t result;
 while (true) {
 result = fread(buffer, 1, pSize, ptrFile);
 
 for (int i = 0; i < result; i++){
 s1 = s1 + buffer[i];
 if (s1 > 65520) s1 %= 65521;
 s2 = s2 + s1;
 if (s2 > 65520) s2 %= 65521;
 }
 if (result != pSize) break;
 }
 
 fclose(ptrFile);
 free(buffer);
 return (s2 << 16) + s1;
 }
 1.6сек, можно уже оставить, но как по мне странно что хеш считается так долго, хотя adler32 во много раз быстрее md5
 
 
 Сообщение отредактировал maksim1221232 - Воскресенье, 17 Июня 2018, 22:19 |  |  |  |  | 
| 
| drcrack | Дата: Воскресенье, 17 Июня 2018, 22:18 | Сообщение # 12 |  | старожил Сейчас нет на сайте | Не пишу на С++ уже давно, поэтому точный код не подскажу, но вообще в таком случае было бы логично использовать неблокирующее чтение, чтобы считать один блок пока грузится следующий |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 22:25 | Сообщение # 13 |  |   старожил Сейчас нет на сайте | drcrack, хорошая идея. Вынеси чтение буффера в функцию таймера. И когда приступаешь считать хеш буффера - в это время читай в таймере следующий буффер! |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 22:45 | Сообщение # 14 |  | заслуженный участник Сейчас нет на сайте | Это мне уже не под силу, в гугле нет примеров которые бы у меня работали. |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 22:52 | Сообщение # 15 |  |   старожил Сейчас нет на сайте | maksim1221232, 
 SetTimer(NULL, 1, 10, TIMERPROC MylpTimerFunc);
 
 TIMERPROC MylpTimerFunc()
 {
 g_bReadReady = FALSE;
 if(g_bNeedRead){ read.... g_bReadReady = TRUE; }
 }
 
 {
 g_bNeedRead = TRUE;
 for (int i = 0; i < result; i++){
 s1 = s1 + buffer[i];
 if (s1 > 65520) s1 %= 65521;
 s2 = s2 + s1;
 if (s2 > 65520) s2 %= 65521;
 }
 g_bNeedRead = FALSE;
 while(!g_bReadReady){;;}
 }
 |  |  |  |  | 
| 
| Quad69 | Дата: Воскресенье, 17 Июня 2018, 23:14 | Сообщение # 16 |  | заслуженный участник Сейчас нет на сайте | Все ровно не понял, оно половину красным подчеркивает. |  |  |  |  | 
| 
| falcoware | Дата: Воскресенье, 17 Июня 2018, 23:19 | Сообщение # 17 |  |   старожил Сейчас нет на сайте | maksim1221232, ладно, это уже высший пилотаж   
 Жду плюса в репу! А все думают, что Фалько лох - ничего не смыслит в программировании. Гуру с 30 лет опыта!!!
   |  |  |  |  | 
| 
| drcrack | Дата: Воскресенье, 17 Июня 2018, 23:43 | Сообщение # 18 |  | старожил Сейчас нет на сайте | Цитата  это уже высший пилотажне, высший это если еще сверху добавить многопоточность
   |  |  |  |  | 
| 
| afq | Дата: Понедельник, 18 Июня 2018, 04:22 | Сообщение # 19 |  |   Разработчик Сейчас нет на сайте | maksim1221232, возможно время ещё занимает выделение памяти, попробуй получить размер файла, и от этого уже знать сколько нужно выделить. Так у тебя проблем не будет с любым размеров файла. Добавлено (18 Июня 2018, 04:19)---------------------------------------------
 Но если размеры файлов очень большие могут быть, то циклическое считывание файла по 512 мб хватит.
 Добавлено (18 Июня 2018, 04:22)---------------------------------------------
 falcoware, а точно нужен таймер, можно же использовать поточную функцию. Посчитал размер файла, один поток одну часть обрабатывает, другой поток другую.
 |  |  |  |  | 
| 
| drcrack | Дата: Понедельник, 18 Июня 2018, 04:29 | Сообщение # 20 |  | старожил Сейчас нет на сайте | Цитата  maksim1221232, возможно время ещё занимает выделение памяти, попробуй получить размер файла, и от этого уже знать сколько нужно выделить. Так у тебя проблем не будет с любым размеров файла.это все ерунда в сравнении с чтением с диска
 современные hdd это около 150 мб/с линейного чтения, а файл 350 мб
 
 
 Цитата  falcoware, а точно нужен таймер, можно же использовать поточную функцию. Посчитал размер файла, один поток одну часть обрабатывает, другой поток другую. по причинам, написанным выше, на самом деле одного потока будет достаточно — ну не сможешь ты получать файл быстрее чем диск его тебе может отдавать
 
 алгоритм примерно такой нужен:
 1. прочитать 1 блок
 2. запросить 2 блок в неблокирующем режиме
 3. считать хеш первого блока
 4. ждать пока 2 блок будет загружен в память
 5. повторять с пункта 2 пока не кончится файл
 
 
 Сообщение отредактировал drcrack - Понедельник, 18 Июня 2018, 04:34 |  |  |  |  |