2012-03-04

ехал value через value

Из "накоженного":
serialize(stream, value.value.value);
if (value.value.value)
    serialize(stream, value.value.kind);

2012-02-23

"оптимизаторы", блин

Прочитал цитату на ITHappends
Смотрю код высоконагруженного сервера. В ядре обсчёта вижу код типа:

func() {
ObjectGame* OG=MainOG;
while(OG->next!=NULL)
{
ia=(int*)OG+12;
i=*ia;
/* что-то делает*/
*ia=i;
/* код функции, внутри функции ia претерпевает различные изменения*/
OG=OG->next;
}
}


С большими глазами иду к прогеру, который это всё написал. Спрашиваю: почему он не пользуется методами Set и Get, и вообще, почему именно 12 байт?

На что он мне отвечает: «Внутри кода функции есть ветвящийся цикл, в котором перебираются многие параметры объекта. Если пользоваться методами Set и Get, а это переход по адресу, причём у каждого объекта он свой, конвейер процессора офигеет и сбросится. Это плюс 30 тактов на каждый переход. Всего таких объектов в секунду надо обсчитать порядка нескольких миллионов. Частота ядра — три миллиарда операций в секунду. Отсюда вывод: идите вы лесом со своим ООП!»

Меня аж передернуло.

>> ia=(int*)OG+12;
а потом этот код скомпилировали другим компилятором, на другой платформе, под другую архитектуру или с другими настройками(тут даже переключение debug/release может выстрелить). И happy debugging готов. Функция продолжает считать быстро, но выдает ошибочный результат.

>>  Если пользоваться методами Set и Get, а это переход по адресу, причём у каждого объекта он свой,
Лолчто?

Отсюда вывод: гнать нахер таких "оптимизаторов" из професии.


2012-01-10

status $ haskell + projectEuler

Продолжаю на досуге мучить haskell и решать задачки с "Проекта Эйлер".
Решил over 90 задач, уже в топ-50 по Украине
Среди знакомых ников в первой сотне есть adept и jdevelop (оба тоже с haskell)
Задачки разные -- в основном всякий матан: простые числа, числа фибоначчи, "фигурные" числа, функция Эйлера, Диофантовы уравнения, цепные дроби, комбинаторика... посчитать сумму, посчитать разность... посчитать кол-во, найти минимум ....
Есть немного динпрога, часто в в виде задач на поиск пути.
Пару задач уже встречал то-ли на ACM, то ли на тренировках к нему.
Из более "прикладных" задач понравилось "54: даны карты двух игроков в покер. определить, сколько раз выиграл первый", "59: дан неизвестный текстовый файл, зашифрованный xor-ом c 3-хсимвольным неизвестным паролем, расшифровать брутфорсом" и "96: написать решалку судоку",

"Pure C" Ненависти Псто.

Пишу обвертку вокруг одной библиотеки, написанной на "сишечке".
  • Пяток структур и полсотни функций в каждом хидере, документирована от силы четверть. Итого -- тысячи функций, которые вроде бы умеют все, но чтобы сделать что-то, на пол-шага отличающееся от примеров, приходится достаточно долго курить, а клиентский код получается весьма обширным. В результате -- за деревьями не видно леса.   
  • Отсутствие модификаторов доступа в С -- мне как клиенту библиотеки непонятно, какие данные я могу менять напрямую, а какие -- через функции библиотеки. Можно было бы спрятать приватные данные в pimpl, но автор до этого не додумался.
  • Pure C реализации вектора/списка/хешмапы. Через void*, по другому ведь никак. Типобезопасность? Нет, не слышали. Хорошо, если комментарий есть -- "в этом списке char*, в этом -- struct foo*. В динамических языках хоть ассерт можно поставить, в С -- либо все ок, либо расстрел памяти.
  • Вау, автор додумался до идеи конструктора/деструктора. Поэтому для каждой струкутры есть
    struct lib_foo * lib_foo_new(/*параметры*/); 
    void lib_foo_free(struct lib_foo*);
    
    даже если это
    struct lib_foobar {
      int fb_foo;
      int fb_bar;
    };
    
    Соответственно, все обьекты выделяются через malloc в хипе, в том числе и члены членов членов членов главной структуры. 
  • А до виртуального деструктора автор не додумался (Или решил, что это оверхед). Поэтому при оборачивании обьекта в умный указатель приходится постоянно передавать ему делитер.
  • Привычка добавлять сокращенное имя структуры как префикс поля (те самые fb_) в примере выше. В результате -- в клиентском коде будет куча копи-пасты вида
    lib_foo_list * fill_foo(...) {
      lib_foo_list * foos = lib_foo_list_new();
      fill(foos->foo_list, ...)
      return foos;
    }
    
    lib_bar_list * fill_bar(...) {
      libbar_list * bars = lib_bar_list_new();
      fill(bars->bar_list, ...)
      return bars;
    }
    
    lib_baz_list * fill_baz(...) {
      libbaz_list * bazs = lib_baz_list_new();
      fill(bazs->baz_list, ...);
      return bazs;
    }
    
    которую не засунуть в шаблон.
  • Попытка сэкономить на копировании приводит к странному контракту функций - если функция завершилась успешно -- она владеет переданными обьектами. Если с ошибкой - то обьектами владеет клиентский код. Отсюда: 
    1. В клиенской функции нужна секция обработки ошибок. 
    2. Это не типичная для "сишечки"
      clear_foo:
        lib_foo_free(foo);
      clear_bar:
        lib_bar_free(bar);
        
      return err; 
      
      а нечто позапутанней с дополнительными return-ами или goto-ми
  • Еще запутанней с функциями, принимающими char*. Одна функция копирует переданную строку, соседняя -- ее "овладевает". Комментариев обычно нет, смотри примеры или исходный код. И да, строки мы копируем через strdup, а длину меряем через strlen.  

2011-12-21

euler-69

Пишешь алгоритм. Он тормозит. Прикидываешь, понимаешь, что в ближайшие сутки он не досчтитает.
Гуглишь. Оптимизируешь. Рассчетное время -- уже в часах.
Видишь закономерность. Рассчет ускорился в несколько раз.
Еще одну. Через пару секунд получаешь ответ.
А потом понимаешь, что ответ можно получить за ту же пару секунд на любом калькуляторе.
Или даже просто посчитать на листике бумаги. 

2011-11-15

пехапешники такие пехапешники:


var $cnonce = "f0ecf39d64caeed767075abcc6bec8bz";// This string should be auto-generated

2011-11-09

Euler

1
sum x = x * n * (n + 1) `div` 2 where n = 999 `div` x
solve = sum 3 + sum 5 - sum (3*5)

2

add x acc = if even x then acc + x else acc
fib a b acc = if b > 4000000 then acc else fib b b' acc'
  where b' = a + b
           acc' = add b acc
solve = fib 1 1 0

3 Пытался делать через решето Эратосфена. Тупит. Тупой брутфорс сразу дал ответ

source = 600851475143 
divide s x  
  | s == x = x
  | s `mod` x == 0 = divide (s `div` x) x
  | otherwise = divide s (x + 2) 

solve = divide source 3

2011-11-01

Happy debugging, bitfield

Все тот же линуховый демон.
Софт работал, работал, а в один "прекрасный" момент после перекомпиляции -- перестал.
Полтора дня пытался понять, кто портит память (прога падала в недрах libc на malloc/free).
....
Два класса с одинаковым названием, лежащие в разных файлах. Отличаются одним полем с нетривиальным ктором/дтором. Оба используются в проекте. Нарушение ОДР в чистом виде.
Happy debugging, bitfield.