воскресенье, декабря 24, 2006

Что мы теряем на Exception'ах в perl?

Наверняка многие интересовались насколько падает производительность при использовании Exception'ов по сравнению с обработкой ошибок по коду возращаемого значения.

Для начала возьмём к примеру Exception::Class и посмотрим сколько мы теряем используя генерацию исключений. Для этого напишем три функции в одной(Err) будет возвращать в случае ошибки код ошибки(в нашем случае 0), во второй(Exc) будем генерить исключение-родителя, в третьей(childExc) будем генерить исключение-потомка(просто в надежде увидеть какое-то чудо :) ).



#!/usr/bin/perl

use strict;
use warnings;
use Carp qw(croak);
use Benchmark qw(:all);
use Exception::Class( 'TestExceptionBase',
'TestExceptionChild' => { isa => 'TestExceptionBase' } );

sub ProcessDub {
my $dub;
for (my $i=0;$i<100;$i++) j =" $i**2;" dub =" $j;" ret =" (" ret =" (">new() ) if ( !$ret );

return $ret;
}

sub childExc {
my ($i,$delay) = @_;

my $ret;
$ret = ( $i % 2 );
ProcessDub() if ($delay);

croak( TestExceptionChild->new() ) if ( !$ret );

return $ret;
}

my $ok_value = 1;
my $err_value = 2;
my $delay;

print "Run with no delay (with error): \n\n";
$delay = 0;

cmpthese(
-2,
{ 'throw' => sub {
eval { Exc( $err_value, $delay); };
},
'errorCode' => sub {
Err( $err_value, $delay );
},
'throwChild' => sub {
eval { childExc( $err_value, $delay ); };
}
}
);

print "\n\n";
print "Run with no delay (without error): \n\n";

cmpthese(
-2,
{ 'throw' => sub {
eval { Exc( $ok_value, $delay ); };
},
'errorCode' => sub {
Err( $ok_value, $delay );
},
'throwChild' => sub {
eval { childExc( $ok_value, $delay ); };
}
}
);

print "\n\n";
print "Run with delay (with error): \n\n";
$delay = 1;

cmpthese(
-2,
{ 'throw' => sub {
eval { Exc( $err_value, $delay); };
},
'errorCode' => sub {
Err( $err_value, $delay );
},
'throwChild' => sub {
eval { childExc( $err_value, $delay ); };
}
}
);

print "\n\n";
print "Run with delay (without error): \n\n";

cmpthese(
-2,
{
'throw' => sub {
eval { Exc( $ok_value, $delay ); };
},
'errorCode' => sub {
Err( $ok_value, $delay );
},
'throwChild' => sub {
eval { childExc( $ok_value, $delay ); };
}
}
);


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



Run with no delay (with error):

Rate throw throwChild errorCode
throw 821/s -- -6% -100%
throwChild 877/s 7% -- -100%
errorCode 628563/s 76506% 71541% --


Run with no delay (without error):

Rate throw throwChild errorCode
throw 438881/s -- -8% -24%
throwChild 475773/s 8% -- -18%
errorCode 579964/s 32% 22% --


Run with delay (with error):

Rate throw throwChild errorCode
throw 806/s -- -1% -93%
throwChild 813/s 1% -- -93%
errorCode 11817/s 1365% 1353% --


Run with delay (without error):

Rate errorCode throw throwChild
errorCode 11727/s -- -2% -3%
throw 11981/s 2% -- -1%
throwChild 12042/s 3% 1% --


Результаты с "пустой"(with no delay) функцией делались для оценки теоретических потерь - на практике у вас будут функции с телом. Итак в самом худшем случае который в реальном мире не встречается нам грозит просто запредельная потеря скорости(примерно в 700 раз) при генерации исключения, и замедление всего на 20-30% если ошибки не произошло.


Также проводились измерения для функции имеющей хоть какое-то отношение к реальному миру. В качестве заглушки там используется возведение чисел с 0 по 99 в квадрат. Для этой функции замедление при ошибке примерно в 10 раз, и всего на 2-3% если ошибки не произошло.


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


среда, декабря 20, 2006

Борьба гигантов с поисковым спамом

Что-то в последнее время всё про спам, да про спам получается писать, хотя есть ещё о чём написать. Ну да ладно, добъём тему.


Вкратце там майкрософт сообщает, что анализа контекста для выявления доров уже стало не хватать, и они готовы применить новое оружие с длинным названием.

Оружие у них должно работать так:
1). Поиск форумов и гестбуков ссылающихся на изначально известные спам-ресурсы, на этих форумах происходит извлечение внешних урл и занесение их в список потенциальных спамресурсов и так до тех пор пока после ряда очередных итераций список спамресурсов не перестанет заметно расти;
2). Далее чтобы отсеять ложные срабатывания запускается ихний Strider URL Tracer , который открывает для каждого url из полученного списка реальный браузер и отслеживает все URL к которым было обращение в результате. В результате создаётся список таких(к которым происходит обращение из url найденных в пункте 1) URL отранжированных по количеству доноров трафика. Если на сайт ссылаются в основном подозрительные сайты и его нет в белом списке (где надо полагать всякие adsens'ы и счётчики), то ему ставится клеймо "Спамер" а всем его донорам выдаётся клеймо "Дорвей".

Дальше товарищи из майкрософт говорят, что для борьбы со спамерами надо использовать их слабости:
1). Заспамленные форумы используются для ловли новых проспамливаемых дорвеев.
2). Чем больше дорвеев для сайта создаст спамер, тем проще его вычислить(см. выше).

В принципе для меня самым интересным здесь является признание факта проверки подозрительных url на реальном браузере. Если это не пустые слова, то достижение победы над seoспамерами - дело техники.

P.S. Там в ссылках по теме к этой статье есть ещё пара интересных заметок. Хотя в целом конечно Пиарщики майкрософта явно поработали против заклятого друга Гугла, но слава богу это не сильно мозолит глаза.

среда, декабря 06, 2006

Опять о captcha

Я недавно писал что стандартные captch'и в виде ввода набора символов уже отжили своё. И тут наткнулся на опровергающий пример. По-крайней мере сходу не могу придумать как такую картинку можно распознать автоматически за более-менее приемлемое время.

Итак сам пример: http://www.ocr-research.org.ua/teabag/2.X.html, http://www.ocr-research.org.ua/teabag/1.X.html.

Очень неплохо на мой взгляд. На том же сайте есть раздел с примерами слабых captcha, с краткой характеристикой: http://www.ocr-research.org.ua/list.html . Кстати список наводит на мысль о русскоязычности владельцев сайта. Они и мтс и км там помянули и еще много русских/украинских сайтов.

среда, ноября 29, 2006

`make test` - полный вывод сообщений каждого теста

Допустим что вы написали один или несколько модулей на perl и много-много тестов для них. В каждом тесте вы подробно выводили сообщения типа "Первая ступень отстыковалась","Корректировка траектории","Отстыковка второй ступени" и т.д.

Наиболее вероятно, что Makefile.PL у вас состоит из вызова WriteMakefile модуля ExtUtils::MakeMaker. Но вот незадача, при `make test` у вас просто напротив каждого тестового файла ставится ok или пишется, что дело труба. И никаких ваших подробных сообщений для каждого теста не выводится, а иногда они существенно сокращают время поиска граблей, если составлены грамотно и в правильном порядке и хотелось бы их видеть(образно выражаясь если первая ступень уже отделилась - там грабли уже вряд ли есть, а если и есть, то нас они не особо интересуют :) ).

Так вот решение существует. Достаточно написать `make test TEST_VERBOSE=1` и вуаля - ваши сообщения посыпяться как жёлуди. Ещё говорят нужно установить переменную окружения HARNESS_VERBOSE: `export HARNESS_VERBOSE=1`. Но лично у меня сейчас работает и без неё. А раньше вроде не работало, вобщем это видимо зависит уже от каждого конкретного случая (ОС/версия софта/настройки).

понедельник, ноября 27, 2006

Антиспам для форума phpBB

Я недавно писал о том что со спамботами вполне можно бороться. Так вот разработчики похоже наконец разродились более менее эффективными модами.

Textual Confirmation - при регистрации задаёт один из указанных админом вопросов, потом сравнивает с корректными вариантами ответов(тоже заданных админом). В принципе если проявить немного фантазии в вопросах, то автоматически его не обойти.

Anti Bot Question MOD - задаёт вопросы при регистрации и/или постинге гостей. В качестве вопросов можно использовать текст, картинки, html. Но устанавливать его гораздо сложнее чем предыдущий мод.

Да, Textual Confirmation в бесплатном варианте отсылает репорт о спаме куда-то там, но не думаю, что стоит волноваться, автор особо не скрывается и не вызывает подозрений. Вот кстати его любопытная статейка о Google Summer Code: http://offline.computerra.ru/2005/611/235848/

воскресенье, ноября 26, 2006

True or False в perl, небольшой логический тупичок

По прочтении статьи указанной ниже придумал задачку. Даны A и B. Про них известно только следующее:
(A==0) -> true
(B==0) -> false
A && B -> B
B && A -> A

Правильный ответ (выдели мышкой чтобы прочитать):
A = <непустая строка>
B = 1

По мотивам True or False? на perlmonks.

Таких вопросов по той статье можно ещё придумать. Правда такие вопросы годятся только для того, чтобы побыстрее избавиться на собеседовании от явно неподходящего претендента на место, т.к. практическая польза от знаний ответов на такие вопросы минимальна.

вторник, ноября 14, 2006

Баги в GWT

Да, не всё безоблачно оказалось в GWT. Сначала обнаружился баг в Опере при попытке вывести PopupPanel немного смещённой относительно нажатой кнопки. В опере getAbsoluteTop() почему-то возвращает 0, причём в google groups сообщения об этом были ещё в августе и ранее.

Далее для борьбы с ложным множественным кликом я написал примерно следующий обработчик клика:
if (addForm==null || !addForm.isVisible())
addForm = new AddForm(id);
Где AddForm - наследник PopupPanel. Но это не работало. Потому что оказывается метод hide() класса PopupPanel не устанавливает Visible в false - пришлось перекрыть hide() в наследнике и вызвать в нём SetVisible(false).

вторник, октября 31, 2006

Вышел GWT 1.2 Release Candidate

Из заявленного особо интересно появление com.google.gwt.http.client, а то возможности HTTPRequest прямо скажем не впечатляли широтой и охватом. Теперь можно работать с заголовками, обрабатывать ошибки вылета по таймауту ну и т.д. и т.п. Т.е. теперь осталось ещё меньше причин для вставок на javascript. Вполне ощутимый шаг вперёд.

Полный список изменений(англ.)

Для upgrade'а в эклипсе я заменил все пути в проекте к старому sdk на новый путь без версии (скажем к примеру на c:\gwt) куда и скопировал новый SDK, затем открыл проект и понажимал на все *.launch файлы в корне. На этом процедура апгрейда была успешно завершена. На ноутбуке запуск в hosted mode стал заметно шустрее.

суббота, октября 14, 2006

Идеи по поводу борьбы с автоспамом форумов

Сейчас наверное нет уже ни одного владельца форума, который не столкнулся бы с проблемой спама. Ну разве что форуму пару дней отроду. Можно конечно тупо удалять вручную спам-посты, но это мягко говоря неразумно - против автоматических средств использовать ручной труд. Активация новых пользователей вручную, captcha - всё это уже давно неэффективно против спамеров.

Чтобы бороться с врагом, надо его изучить. Итак приступим к обзору вооружения спамеров. Для современных продвинутых спамилок не проблема авторегистрироваться с верификацией по e-mail, обходить практически любые более-менее распространённые captcha и некоторые спамилки даже умеют преодолевать некоторые распространённые защиты с помощью javascript'а. Но тем не менее спамилка - это просто программа и никакого искусственного интеллекта там нет.

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

Итак где мы можем помешать роботу зарегистрироваться? Ну например воткнуть фотографию со слоном и попросить написать что изображено на картинке. Естественно фотографий должно быть несколько и желательно периодически добавлять новые, удаляя старые, чтобы защититься от тупого ввода в базу шаблона для конкретно вашего форума.

Также для защиты можно использовать то, что спамерские боты не умеют исполнять javascript. Например на странице с отправкой поста вставить javascript, который вставит в форму скрытый элемент с определённым значением - так как бот не умеет выполнять javascript, то он не сможет вставить этот элемент и присвоить ему указанное значение. Так как по идее боты могут проанализировать javascript на примитивном уровне, то желательно воспользоваться замечательной функцией eval чтобы скрыть наше намерение вставить элемент в форму и присвоить ему определённое значение.

В принципе таких методов хватит для успешной борьбы с автоспамом форумов.

Изучая баги браузеров. История которая никогда не кончится

На этот раз я столкнулся с багом Оперы существующим как показал поиск с древних времен. А именно багом связанным с игнорированием свойства selected элемента option. Т.е. я попытка установить выбранный элемент списка путем установки selected у конкретного option не работает в опере, причем похоже только в ней. Естественно проблема решается через установке selectedIndex: select.selectedIndex = selIndex. Но всё равно, лично меня поразило что проблема не решается годами. Если такое было бы в IE, я бы не удивился.

Тут прочёл о том что багов то у Оперы судя по всему не мало. К примеру выяснили, что опера не понимает десятичные доли процента, а также версия 9.02 имеет непонятный баг при переходе на ссылку с анкором равным id элемента. Подробнее об этом читайте и смотрите здесь: http://xhtml.ru/experiment/browser_day/ .

Ну и назакуску - полезный ресурс с багами IE: http://www.positioniseverything.net/explorer.html .

четверг, сентября 21, 2006

Нелогичность с class и className в IE

Стояла задача: динамически создать див определённого стиля с текстом и воткнуть его в другой. Так как вобщем-то javascript я изучал зная уже не один и даже не два языка программирования, то я написал код так как мне показалось логично. Ниже демонстрационный код того что получилось(дизайна как такого нет - это просто демка):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1251">
<title>IE JS CSS</title>
<style type="text/css">
.grayItalic {
font-style:Italic;
background-color:#CCCCCC;
}
</style>
<script type="text/javascript">
function insertCustDiv(ownerID,classname,text) {
var div=document.createElement('div');
div.setAttribute('class',classname);
div.appendChild(document.createTextNode(text));
document.getElementById(ownerID).appendChild(div);
}
</script>
</head>
<body>


<div style="background-color:#CCCCCC;width:250px;">
<form action=""><fieldset>
<legend>Вставка div'а с текстом</legend>
<input type="button" onclick="javascript: insertCustDiv('divToInsert','grayItalic','Just text');" value="Нажми чтобы вставить">
</fieldset></form>
</div>

<div style="background-color:#FFFF66;width:300px;" id="divToInsert">Вставка будет сюда</div>

</body>
</html>

Пример выводит форму с одной кнопкой и div куда будет производится вставка:



При нажатии на кнопку в Firefox'е и Опере вставляемый div имеет стиль заданный классом grayItalic, т.е. серый фон и наклонный шрифт:



IE же при вставке div'а игнорирует стиль и вставляет без учёта стиля:


В чём же дело? Я не зря упомянул, что javascript не первый мой язык и соответственно я написал код в привычном мне стиле:


function insertCustDiv(ownerID,classname,text) {
var div=document.createElement('div');
div.setAttribute('class',classname);
div.appendChild(document.createTextNode(text));
document.getElementById(ownerID).appendChild(div);
}

Вроде бы всё логично(особенно для тех кто привык работать с xml), но на самом деле в W3C DOM для указания class для элемента есть специальное свойство - className (которое судя по описанию как раз и устанавливает аттрибут class, но как известно IE не особо волнуют всякие там стандарты). Переписываем вот так:


function insertCustDiv(ownerID,classname,text) {
var div=document.createElement('div');
div.className = classname;
div.appendChild(document.createTextNode(text));
document.getElementById(ownerID).appendChild(div);
}


И всё работает в IE тоже.

Аналогично не работает установка аттрибута "for" (для элемента label), вместо этого надо использовать свойство "htmlFor". Сложнее обстоит дело со "style", может позже напишу об этом.