Страницы

понедельник, 16 мая 2011 г.

Не слушайте

Не слушайте их, когда они говорят, что ваша идея бесперспективна.
Когда говорят, что идея должна быть Идеей.
Эти перфекционисты, мой бог, они говорят вам, что лучше потратить год на отладку.
Они говорят, что пользователи капризны и не примут проект с недоработками.
Вы предпочитаете слушать их? Тех, которые из-за своего перфекционизма сами ничего не запустили?
Это лучшая отмазка для тех, кто не хочет пытаться – «Либо надо сделать идеально, либо не делать.»
Идеал недостижим. Нет предела совершенству. Проект всегда будет недоработан. Такова природа бытия.
Поэтому, не тяните. Не тяните с запуском стартапа.
Энтузиазм пропадает. Появляются новые идеи. Меняются планы.
Просто запускайте, поглощайте критику, улучшайте. Главное – это готовая основа.

Не слушайте их. Слушайте себя.

вторник, 10 мая 2011 г.

Use perl или продолжаем оптимизацию

Бродил по коду проекта на новой работе и набрел на такую вот функцию :


sub translit
{
my $text = shift;
$text = "$text";

$text =~ s/А/A/g;
$text =~ s/Б/B/g;
$text =~ s/В/V/g;
$text =~ s/Г/G/g;
$text =~ s/Д/D/g;
$text =~ s/Е/E/g;
$text =~ s/Ё/E/g;
$text =~ s/Ж/ZCH/g;
$text =~ s/З/Z/g;
$text =~ s/И/I/g;
$text =~ s/Й/J/g;
$text =~ s/К/K/g;
$text =~ s/Л/L/g;
$text =~ s/М/M/g;
$text =~ s/Н/N/g;
$text =~ s/О/O/g;
$text =~ s/П/P/g;
$text =~ s/Р/R/g;
$text =~ s/С/S/g;
$text =~ s/Т/T/g;
$text =~ s/У/U/g;
$text =~ s/Ф/F/g;
$text =~ s/Х/H/g;
$text =~ s/Ц/C/g;
$text =~ s/Ч/CH/g;
$text =~ s/Ш/SH/g;
$text =~ s/Щ/SCH/g;
$text =~ s/Ь/'/g;
$text =~ s/Ъ/'/g;
$text =~ s/Ы/Y/g;
$text =~ s/Э/E/g;
$text =~ s/Ю/YU/g;
$text =~ s/Я/YA/g;
$text =~ s/а/a/g;
$text =~ s/б/b/g;
$text =~ s/в/v/g;
$text =~ s/г/g/g;
$text =~ s/д/d/g;
$text =~ s/е/e/g;
$text =~ s/ё/e/g;
$text =~ s/ж/zch/g;
$text =~ s/з/z/g;
$text =~ s/и/i/g;
$text =~ s/й/j/g;
$text =~ s/к/k/g;
$text =~ s/л/l/g;
$text =~ s/м/m/g;
$text =~ s/н/n/g;
$text =~ s/о/o/g;
$text =~ s/п/p/g;
$text =~ s/р/r/g;
$text =~ s/с/s/g;
$text =~ s/т/t/g;
$text =~ s/у/u/g;
$text =~ s/ф/f/g;
$text =~ s/х/h/g;
$text =~ s/ц/c/g;
$text =~ s/ч/ch/g;
$text =~ s/ш/sh/g;
$text =~ s/щ/sch/g;
$text =~ s/ь/'/g;
$text =~ s/ъ/'/g;
$text =~ s/ы/y/g;
$text =~ s/э/e/g;
$text =~ s/ю/yu/g;
$text =~ s/я/ya/g;
$text =~ s/і/i/g;
$text =~ s/ї/yi/g;
$text =~ s/є/e/g;

return $text;
}


Подумал про себя, чем не развертывание цикла, хоть и слегка...ммм, в общем не будем об этом.
Как вы догадались, это функция перевода в транслит текста, а теперь важный момент текста в sms сообщениях. Функция сразу выглядела ужасно, но как показали дальнейшие изыскания она имеет право на существование. Модифицируем ее


sub translit_new_cycle
{
my $text = shift;
my %hash_=(
'А'=>'A',
'Б'=>'B',
'В'=>'V',
'Г'=>'G',
'Д'=>'D',
'Е'=>'E',
'Ё'=>'E',
'Ж'=>'ZCH',
'З'=>'Z',
'И'=>'I',
'Й'=>'J',
'К'=>'K',
'Л'=>'L',
'М'=>'M',
'Н'=>'N',
'О'=>'O',
'П'=>'P',
'Р'=>'R',
'С'=>'S',
'Т'=>'T',
'У'=>'U',
'Ф'=>'F',
'Х'=>'H',
'Ц'=>'C',
'Ч'=>'CH',
'Ш'=>'SH',
'Щ'=>'SCH',
'Ь'=>"'",
'Ъ'=>"'",
'Ы'=>'Y',
'Э'=>'E',
'Ю'=>'YU',
'Я'=>'YA',
'а'=>'a',
'б'=>'b',
'в'=>'v',
'г'=>'g',
'д'=>'d',
'е'=>'e',
'ё'=>'e',
'ж'=>'zch',
'з'=>'z',
'и'=>'i',
'й'=>'j',
'к'=>'k',
'л'=>'l',
'м'=>'m',
'н'=>'n',
'о'=>'o',
'п'=>'p',
'р'=>'r',
'с'=>'s',
'т'=>'t',
'у'=>'u',
'ф'=>'f',
'х'=>'h',
'ц'=>'c',
'ч'=>'ch',
'ш'=>'sh',
'щ'=>'sch',
'ь'=>"'",
'ъ'=>"'",
'ы'=>'y',
'э'=>'e',
'ю'=>'yu',
'я'=>'ya',
'і'=>'i',
'ї'=>'yi',
'є'=>'e',
' '=>' ',
"\n"=>"\n"

);
my @a=split(//,$text);
foreach(@a){
$_=$hash_{$_};
}


#
return join("",@a);
}


А теперь тестируем и...

#!/usr/bin/perl
use strict;
use Benchmark qw(:all);
use Data::Dumper;
use utf8;


my @a=(
"Я родил собаку это меня убило как же все тупо Я родил собаку это меня убило как же все тупо"

);


my $count=100000;

foreach(@a){
timethese($count, {
'may be good' => "translit_new_cycle('$_')",
'may be bad' => "translit('$_')",
});
}


получаем

may be bad: 11 wallclock secs (10.24 usr + 0.00 sys = 10.24 CPU) @ 9765.62/s (n=100000)
may be good: 12 wallclock secs (10.45 usr + 0.00 sys = 10.45 CPU) @ 9569.38/s (n=100000)

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

Benchmark: timing 100000 iterations of may be bad, may be good...
may be bad: 3 wallclock secs ( 2.63 usr + 0.00 sys = 2.63 CPU) @ 38022.81/s (n=100000)
may be good: 5 wallclock secs ( 4.96 usr + 0.00 sys = 4.96 CPU) @ 20161.29/s (n=100000)


Но увеличившая разница во времени( почти в два раза) насторожила, введем очень длинную строку для тестов "Я родил собаку родил собаку это меня убило как же все тупо родил собаку это меня убило как же все тупо родил собаку это меня убило как же все тупо родил собаку это меня убило как же все тупо"

may be bad: 22 wallclock secs (18.29 usr + 0.02 sys = 18.31 CPU) @ 5461.50/s (n=100000)
may be good: 22 wallclock secs (17.58 usr + 0.01 sys = 17.59 CPU) @ 5685.05/s (n=100000)



О ура наконец мы победили...но в чем же дело, а дело в хеше, оказывается его инициализации
занимает львиную долю времени, и если его сделать глобальным, каким он в принципе и должен быть получим , примерно так

my %hash_=(
'А'=>'A',
'Б'=>'B',
'В'=>'V',
'Г'=>'G',
'Д'=>'D',
'Е'=>'E',
'Ё'=>'E',
'Ж'=>'ZCH',
'З'=>'Z',
'И'=>'I',
'Й'=>'J',
'К'=>'K',
'Л'=>'L',
'М'=>'M',
'Н'=>'N',
'О'=>'O',
'П'=>'P',
'Р'=>'R',
'С'=>'S',
'Т'=>'T',
'У'=>'U',
'Ф'=>'F',
'Х'=>'H',
'Ц'=>'C',
'Ч'=>'CH',
'Ш'=>'SH',
'Щ'=>'SCH',
'Ь'=>"'",
'Ъ'=>"'",
'Ы'=>'Y',
'Э'=>'E',
'Ю'=>'YU',
'Я'=>'YA',
'а'=>'a',
'б'=>'b',
'в'=>'v',
'г'=>'g',
'д'=>'d',
'е'=>'e',
'ё'=>'e',
'ж'=>'zch',
'з'=>'z',
'и'=>'i',
'й'=>'j',
'к'=>'k',
'л'=>'l',
'м'=>'m',
'н'=>'n',
'о'=>'o',
'п'=>'p',
'р'=>'r',
'с'=>'s',
'т'=>'t',
'у'=>'u',
'ф'=>'f',
'х'=>'h',
'ц'=>'c',
'ч'=>'ch',
'ш'=>'sh',
'щ'=>'sch',
'ь'=>"'",
'ъ'=>"'",
'ы'=>'y',
'э'=>'e',
'ю'=>'yu',
'я'=>'ya',
'і'=>'i',
'ї'=>'yi',
'є'=>'e',
' '=>' ',
"\n"=>"\n"

);

sub translit_new_cycle
{
my $text = shift;

my @a=split(//,$text);
foreach(@a){
$_=$hash_{$_};
}


#
return join("",@a);
}


то получим наконец то, что ожидали...Хотя в принципе можно и лучше, например если заменить хеш, массивом, а цикл развернуть, так как длинна смс все таки фиксированная..


may be bad: 23 wallclock secs (18.13 usr + 0.00 sys = 18.13 CPU) @ 5515.72/s (n=100000)
may be good: 17 wallclock secs (13.86 usr + 0.02 sys = 13.88 CPU) @ 7204.61/s (n=100000)

На более коротких текстах типа SMS, наша процедура выигрывает с преимуществом в два раза.

Собственно к чему я это...Наверно к тому что панацеи не существует