· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.A&O —› Вот и хеши пошли...

. 1 . 2 . 3 . 4 . 5 . >>

Посл.отвђт Сообщенiе


Дата: Авг 28, 2003 23:57:36 · Поправил: Безпощадный даос

Итак, господа. Новая проблемка для алгоритмизаторов. Заранее спасибо за помощь!

Имеем функцию:

hugefunction(char *func_name);

которая принимает на вход имя функции, которую она должна выполнить и зовет функцию с этим именем. Где-то так:
hugefunction(char *func_name)
{
  ...
  if(!strcmp(func_name, "do_this"))
     do_this();
  else if(!strmp(func_name, "do_that"))
     do_that();
  else if ... еще хренова туча сравнений
     
... и вызовов функций при необходимости...
}


Очевидно, функция далека от идеала. Если, скажем, имя "do_it_at_last" стоит в самом конце, то можно подсчитать, сколько времени потратится на то, чтобы добраться до нее!
Далее в этом же файле стоит непосредственно исходный код функций do_this, do_that, do_it_at_last и т.п.
Как это дело можно улучшить? Ну, первое, что приходит на ум, это взять и подсчитать хеши функций и вписать их в файл вместо имен и сравнивать не строки, а хеши, т.е. unsigned long или что-то еще. Уже быстрее. Тогда нужна хорошая хеш-функция без коллизий.
А теперь вопросы к спецам
1) Какая такая есть хорошая функция, чтобы на выходе unsigned long получить?
2) Вероятно, можно еще более улучшить производительность, скажем, создав какой-нибудь массив, отсортировать его и находить там элемент бинарным поиском, а что потом - я пока не дотумкал?
Ну что, кто меня будет пинать :)


Дата: Авг 29, 2003 00:16:57

2) looks very nice.
typedef int (*FUNCTYPE) (int, char*);

typedef struct
{
  char* pstrFuncName;
  FUNCTYPE pfnCallThisCode;
}
FUNCMAPSLOT;

// Prototypes:
int foo1 (int, char*);
int foo2 (int, char*);
int foo3 (int, char*);

// Map itself:
FUNCMAPSLOT mapAll [] = {
  { "foo1", foo1 }, // Can be optimized with ## operators
  { "foo2", foo2 },
  { "foo3", foo3 },
};

// Bodies:
int foo1 (int, char*)
{
  return 0;
}

int foo2 (int, char*)
{
  return 0;
}

int foo3 (int, char*)
{
  return 0;
}

// Sort the 'mapAll' by 'pstrFuncName':
// TODO: ...

// And then with binary search call the entry's
// member 'pfnCallThisCode'.

It works with the 'foo_xxx()' where parameters are the same, but with diff. parameters you need to 'trick' compiler...


Дата: Авг 29, 2003 00:25:53

AsmGuru62

1) Меня не слишком вдохновляет, что имена в mapAll символьные, а не хеши - это медленно.
2) ПРИНЦИПИАЛЬНОЕ ограничение на параметры функции - лучше бы как-то хранить массив и поинтеров на функции, который создавать динамически и заполнять его по мере надобности (только я не знаю как %()


Дата: Авг 29, 2003 00:50:34

Да, статья по основам хеширования лежит на RSDN.ru. И еще - язык - именно С. Алгоритм можно проиллюстрировать и на С++, но STL мне предлагать использовать не надо. Еще раз спасибо.


Дата: Авг 29, 2003 00:55:03

А что если подставить в эту же структуру CRC32 от имени функции? Перед сортировкой пройтись по именам функций и сделать для них CRC32.
typedef struct
{
  char* pstrFuncName;
  FUNCTYPE pfnCallThisCode;
  UINT crc32FuncName; // Sort and binary scan for this!
}
FUNCMAPSLOT;


Дата: Авг 29, 2003 00:56:33

volodya
А как часто надо динамически строить такие массивы?


Дата: Авг 29, 2003 00:59:28

Очень хорошо. CRC32 вот:
unsigned hashCrc(char *string)
/* Returns a CRC value on string. */
{
	unsigned char *us = (unsigned char *)string;
	unsigned char c;
	unsigned shiftAcc = 0;
	unsigned addAcc = 0;

	while ((c = *us++) != 0)
	{
		shiftAcc <<= 2;
		shiftAcc += c;
		addAcc += c;
	}
	return shiftAcc + addAcc;
}


Т.о. мы решили проблему с CRC32. Далее, ты предлагаешь заводить структуры... Т.е. массив из структур. Как часто его надо создавать? Это CGI приложение. Следовательно, на каждый http-запрос надо его запускать и создавать такой массив. Только я не понимаю ту его часть, что с pstrFuncName и pfnCallThisCode - она не будет работать %(


Дата: Авг 29, 2003 02:52:04

Вообще я не понимаю пока особо эти указатели на функции. Скорее всего, на стадии компиляции, теоретически, это нереализуемо. Значит, скорее всего, от массива с void * придется отказаться. Вероятно, это будет что-то со switch/case. Или я не прав?


Дата: Авг 29, 2003 02:56:31

AsmGuru62
А зачем пихать в структуру и "имя ф-ции" и CRC32? Достаточно хранить только CRC32 (+ адрес ф-ции, ессно).

volodya
А hugefunction(char *func_name) нельзя переделать в hugefunction(UINT crc)? Пусть клиентская часть приложения считает CRC вместо серверной части. Обычно принято перекладывать максимум работы на клиента.


Дата: Авг 29, 2003 03:20:51

Quantum

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


Дата: Авг 29, 2003 04:04:19 · Поправил: Quantum

volodya
Только я не представляю как можно запихнуть в структуру адрес функции.
typedef int (CALLBACK *FARPROC)();
struct myStruct{
FARPROC address;
UINT crc32;
};


Дата: Авг 29, 2003 04:34:02 · Поправил: volodya

Да нет, не совсем то. Во-первых, почему после typedef идет int. Во-вторых, как туда положить РЕАЛЬНЫЙ адрес? В третьих - функция может вернуть вовсе не int, а, скажем, char *, а то и вообще указатель на сложную структуру... По-моему, тут решения нет. :((((


Дата: Авг 29, 2003 04:38:56

volodya
почему после typedef идет int
Потому что адрес 32-битный.

как туда положить РЕАЛЬНЫЙ адрес?
myStruct test;
test.address = (FARPROC)myFunction;
// . . .
void myFunction(void){}

... или я опять не совсем понял?


Дата: Авг 29, 2003 06:05:12 · Поправил: volodya

test.address = (FARPROC)myFunction;

т.е. заполнение динамическое! Т.е., если массив содержит, скажем, 300 функций, мне что, звать все 300 функций? Может уже я не очень понимаю?

Логика программы:
/*подготовка массива, что включает в себя, ну...
скажем так, я бы просто хранил все подсчитанные суммы
внутри файла как хеш, т.е. массив из структур выглядел бы так:

array[0] -> 123456, void*
array[1] -> 789012, void* и т.п.
Т.е. часть массива готовится уже на стадии компиляции, а для добавления новой функции написать малюсенькую программу, которая пересчитает имя в хеш, а хеш добавлять в .c-файл.*/


hugefunction(char *func_name)
{
   hash = hashCrc(char *func_name); //вычисляем, к сожалению, на стороне сервера

   qsort(наш родимый массив из структур);
   bsearch(в массиве из структур ищем hash);

   //далее каким-то магическим образом берем поинтер на эту функцию
  ну а далее просто вызывается нужная функция;
  //так я себе это мыслю...

}



Дата: Авг 29, 2003 06:08:41

Quantum

Главное требование к этому коду, как и ко всему коду, что я пишу - это то, что он должен успешно компилироваться и работать под 3 осями минимум - Windows/Linux/Solaris - под Солярисом у нас стоят спарки, а это значит, что Я НЕ МОГУ РАССЧИТЫВАТЬ НА ТО, ЧТО АДРЕС БУДЕТ 32-битным.

. 1 . 2 . 3 . 4 . 5 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.093