Страницы

четверг, 19 марта 2009 г.

IF или религия

В этом посте все просто...Каждый программист даже самый ебанутый на голову задумывается о быстродействии своего кода в фундаментальном контексте( то есть хотя бы в контексте языка на котором он пишет)...Грубо говоря рано или поздно он начинает понимать, что куча операторов ветвления замедляют программу, вызовы процедур тоже,циклы тоже...
Фигасе , как свойственно человеку , мы вдаемся в крайности - то есть начинаем избегать лишнего их использования , а этого мы можем добиться только либо использую более сложные структуры данных , либо более извилистый(закавыристый) код ...
Далее мы рождаем две следующие проблемы
1) наш код становится менее понятным( и для нас самих через месяц другой )
2) Его изменение становится очень трудоемким ( простой пример если один флаг используется повсеместно везде или одна переменная для всех циклов в процедуре )

Бзз это убивает наше время...Мы трудным путем идем к идеалу и в то же время от него отталкиваемся - потому что перманентного идеала не существует,или можно перефразировать так идеал вещь относительная...
Суть в том что количество операций процессора исчисляется миллиардами в секунду, а и по сравнениею с этим избавление от одного if и экономление
нескольких десятков операций не имеет значения....
Пример из повседневной жизни программиста - проверка введенных значений формы первые два варианта событий для ООП:
1) Придумываем глобальный класс ,потом для каждой формы наследуем от этого класса и работаем
2) для каждой формы написать процедуру проверки с несколькими своими if-ами

В первом варианте мы потратим время на придумывание подходящей архитектуры,а потом, недели через две, будем со скрипом вспоминать как натягивать конкретный пример.
Во-втором примере мы будем знать куда лезть ,чтоб быро все поправить.
В итоге в первом примере мы выиграем допустим 10 милисекунд( это дохрена вообще-то), но эти милисекунды спокойно схаваються к примеру при маршрутизации пакетов по сети. Даже при клиентском приложении пользователь не заметит разницы в 10 милисекунд. И нахера вы спрашивается мудохались....
Но допустим вам надо собрать статистику с 1000 записей....Разница понятна...Об это был предыдущий пост в этом блоге.

среда, 18 марта 2009 г.

Хеши и JavaScript

Короче задолбало все время вспоминать как делаються нормально хеши в JavaScript потому запишу здесь

var hash = new Object();
var anotherHash = {};

Создание и инициализация массива выглядит следующим образом:
var hash = {"element1": "value2",
"element2": "value2",
"testKey": "testValue"};

Получить значение хеша по ключу можно 2-мя способами: либо обратится как к элементу массива,
используя в качестве индекса ключ - hash['testKey'], либо как к свойству объекта - hash.testKey.

Аналогичным образом происходит и изменение хеша, в случае когда элемент
не существует, он будет создан:
hash['element1'] = 'question';
hash.element2 = 'baz';

hash['answer'] = '42';
hash.foo = 'bar';

Пройтись по всем элементам массива можно используя for:
for( var item in hash ) {
alert(hash[item]);
}

четверг, 5 марта 2009 г.

Оптимизация,Xs,Perl и нахера это все нужно

Вообще этот пост является продолжением темы про идеальные языки.

Грубо говоря то xs это язык описания клея(интерфейся), которым вы будете связывать свою подпрограмму на perl c подпрограммой на C. Если вчитываться в доку , то вы буквально найдете перевод предыдущего предложения на английском.
Доку можно почитать здесь perlxs вернее perldoc perlxs ;). Она довольно обширная и меня не покидала мысль иногда а нахрена столько всего.Но я мужественно дочитал все до конца,а потом не не обнаружил нормального примера... Не сказать что меня это сильно расстроило но все же,учитывая сколько всего было прочитано ,стоял вопрос с какого конца надо подобраться.
Бла.бла.бла я как человек ленивый в конце концов нашел то что мне надо...
Утилита h2xs это именно то, что по-моему требуется сначала. Это утилита напишит весь код xs за вас, да еще и может сама модуль сгенерить.А ее глюки вы уж простите подправите сами,прочитав таки perlxs.

Краткий экскурс по h2xs

Допустим надо сделать модуль Neural - для нейронных сетей и реализацию его написать на С.
Начнем

h2xs -Afn Neural


Создаст пустой модуль со всеми атрибутами порядочного модуля Perl : Makefile.PL,Neural.pm и т.д.
Далее копируем например Neural.h и Neural.c в папку модуля
и выполняем следующую команду

h2xs -Oxan Neural Neural.h

Ну модуль готов с файлом xs.Выполняем perl Makefile.PL, make, make install и юзаем.За остальными вопросами обращайтесь man h2xs

А тут реальное говно,пардон 'Пример из жизни'.

Реальный пример, который много времени портил мне жизнь. В проекте тонким местом были большие объемы простых текстовых данных, есно они брались из базы данных,есно они обрабатывались и форматировались. Обратите внимание на слово форматировались. Нормальной выборкой содержала допустим 2000 записей, и в них могло содержаться от 1 до 5 числовых полей. Потребовалось форматирование по разрядам всех чисел. То есть из '1000000' сделать '1 000 000'.

RegExp!
Первое, что приходит в голову. Потом грубые прикидки и идея regexp -а для 2000 записей это от 2000 до 10000 как то мне не понравилась хотя бы из-за расходов памяти...Написал тогда я первый вариант процедуры разбития на разряды.


sub format_float
{
my $f=shift;
$f=~/([\-])?(\d+)\.(\d{1,2})$|([\-])?(\d+)/;

my $d='';
my $mines='';

unless($3)
{
$f=$5;
$mines=$4;
}else
{
$mines=$1;
$d=".$3";
$f=$2;
}
my @ar=split(//,$f);
my $size=@ar;
my $i=0 ;
my $res;
my $j=0;
$res.="$d";
for($i=$size-1;$i>=0;$i--)
{
unless($j)
{
$res=$ar[$i].$res;
$j++;
}else
{
$res=' '.$res unless($j%3);
$res=$ar[$i].$res;
$j++;
}

}
return $mines.$res;
}

За это долго сам себя буду пинать ногами,но надо было что-то сделать,а сверху пинали требовали заняться другим и т.п. Когда все утихло ,я вернулся к этому куску.Меня дико не устраивало,что обработка выборки занимала для любимых 2000 от 1 до 1.5 секунд.Сделаем regexp к слову это вариант перлиста коммуниста

sub regexp_format_float
{
my $f=shift;
$f=normal_prec($f);

# $f=~s/(\d{1,3})(?=\d{3})/$1 /g;
$f=~s/(\d{1,3})(?=((\d{3})+)\D?)/$1 /g;
return $f;
}

Причем при тесте производительности чисто лишь процедур в среднем вариант c reg-exp-ом был раза в три быстрее первого.Фигасе но при реальном тестирование такого прироста не наблюдалось.Вот тут вспомним про С и XS. Напишем format_float.h , где определим

char * C_format_float(double);

и format_float.c


#include
#include
#include



char * C_format_float(double num)
{
char buffer[60];
char *str,*str1;
char * str_out;
int i,size,j,z,ext;
char tmp;

sprintf(buffer, "%f", num);

size=strlen(buffer);

str=strtok(buffer,".");

size=strlen(str);
ext=(int)size/3;
str_out = malloc(100);


j=0;//
size--;
z=1;//reverse index
for(i=size;i>=0;z++,i--)
{

tmp=str[i];
str_out[i-j+ext]=tmp;
if((z%3)==0)
{
j++;
tmp=' ';
str_out[i-j+ext]=tmp;
}


}
str_out[size+ext+1]='.';
//str_out[size+ext+2]='\0';
str=strtok(NULL,".");
if(str==NULL) return str_out;
str_out[size+ext+2]=str[0];
str_out[size+ext+3]=str[1];
str_out[size+ext+4]='\0';
//strcat(str_out, str);
return str_out;
}

Потом проведем операции из первого абзаца:

bash # h2xs -Afn Format
bash # cp /home_dir/xs/format_float.* /home_dir/Format/
bash # h2xs -Oxan Format format_float.h

Готово можно подключать...Далее могу сказать, что здесь я остановился в оптимизации данного куска кода. В данном случае я говорю о функции char * format_float(double num).Ибо написав скрипт , чтоб посмотреть разницу во времени для всех реализаций

#!/usr/bin/perl
use lib q(.);
use SiteCommon;#содержит процедуры формаирования на Perl
use Format;# C -реализация
use Benchmark qw(:all) ;

timethese(100000, {
'format_float without regexp' => sub { SiteCommon::format_float(1000000.00) },
'format_float on C' => sub { Format::C_format_float(1000000.00) },
'format_float with regexp' => sub { SiteCommon::regexp_format_float(1000000.00) },

});

timethese(100000, {
'format_float without regexp' => sub { SiteCommon::format_float(10000.00) },
'format_float on C' => sub { Format::C_format_float(10000.00) },
'format_float with regexp' => sub { SiteCommon::regexp_format_float(10000.00) },

});
timethese(100000, {
'format_float without regexp' => sub { SiteCommon::format_float(11.00) },
'format_float on C' => sub { Format::C_format_float(10.00) },
'format_float with regexp' => sub { SiteCommon::regexp_format_float(13.00) },

});

Получили примерно следующие результаты


Benchmark: timing 100000 iterations of format_float on C, format_float with regexp, format_float without regexp...
format_float on C: 1 wallclock secs ( 0.31 usr + 0.03 sys = 0.34 CPU) @ 294117.65/s (n=100000)
(warning: too few iterations for a reliable count)
format_float with regexp: 2 wallclock secs ( 2.12 usr + 0.09 sys = 2.21 CPU) @ 45248.87/s (n=100000)
format_float without regexp: 5 wallclock secs ( 5.58 usr + 0.10 sys = 5.68 CPU) @ 17605.63/s (n=100000)
Benchmark: timing 100000 iterations of format_float on C, format_float with regexp, format_float without regexp...
format_float on C: 0 wallclock secs ( 0.30 usr + 0.01 sys = 0.31 CPU) @ 322580.65/s (n=100000)
(warning: too few iterations for a reliable count)
format_float with regexp: 2 wallclock secs ( 1.84 usr + 0.08 sys = 1.92 CPU) @ 52083.33/s (n=100000)
format_float without regexp: 7 wallclock secs ( 4.81 usr + 0.18 sys = 4.99 CPU) @ 20040.08/s (n=100000)
Benchmark: timing 100000 iterations of format_float on C, format_float with regexp, format_float without regexp...
format_float on C: 0 wallclock secs ( 0.27 usr + 0.01 sys = 0.28 CPU) @ 357142.86/s (n=100000)
(warning: too few iterations for a reliable count)
format_float with regexp: 2 wallclock secs ( 0.70 usr + 0.00 sys = 0.70 CPU) @ 142857.14/s (n=100000)
format_float without regexp: 4 wallclock secs ( 3.76 usr + 0.11 sys = 3.87 CPU) @ 25839.79/s (n=100000)

Чем больше число для форматирование тем больше выигрыш в скорости,правда не удивительно, вот только разрыв между реализацией на С и regexp -ом оказался в 8 раз для самого большого тестируемого числа.

среда, 4 марта 2009 г.

Идеальный язык и с чем его едят

Ну в нынешнем разнообразии языков программирования высокого уровня можно потеряться)) ведь неправда ли)) А красноглазики с пеной у рта доказывают , что именно их язык лучше... Другие красноглазики спорят, что лучше ООП или ПОП(процедурно ориентированное )... Во все этом я совершенно потерялся,потерялся я главным образом потому,что один мой товарищ вместе, с которым мы начинали писать и осваивать этот неоднозначный мир,сказал,что глубоко имел ввиду Perl, что он не прочь перейти на java-у,ruby или даже python. Это случилось полгода назад...И сидя с больной ногой дома , я снова вернулся к этой теме.
Я пишу на perl , потому что мне это удобно,люди пишут на php -потому что это удобно,люди пишут на C , потому что это удобно....Знаете почему им удобно, потому что язык программирования - это инструмент ,который придумывали для решения каких-то целей.А хороший инструмент должен быть удобен, на то он и инструмент.И продолжу мысль ,и у каждого инструмента есть свое применение - ведь не будет вы в самом деле забивать гвозди отверткой( конечно можно и сам так делал,но согласитесь неудобно).
Потому мой perl еще долго жить в моем сердце. Но мы ж говорим про идеальные языки , а инструмент не может быть идеальным по своему определению, если его попытаться сделать идельным он станет настолько громоздким и не удобным, что перестанет быть идеальным,так как им тупо херево пользвоаться.
Тогда а что нам делать,когда вот есть проект для его написания используется какой-то конкретный инструмент.Но с развитием проекта его задачи расширились, и используемый инструмент перестал отвечать части задачь проекта...Тут начинается изобретение велосипеда - плохой вариант, или воспользоваться вторым вариантом использовать другой инструмент.
Благо все языки поддержуют возможность написания расширений на других языках. Для моего горячо любимого Perl есть такая штука как xs ;), для php есть всякие streams,java вообще имеет чуть ли не встроенную поддержку использования кода на C. Так вот как слесарь ходит с чемоданом отверток, так и в программировании есть чемодан языков уместное использование кадого из них и будет давать нам результат близкий к идеальному)