1. PHP 5.3.0 (namespaces, mysqlnd, late static binding, оператор ?:, замыкания и лямбда-функции, удалена поддержка режима совместимости zend.ze1, добавлена константа __DIR__)
2. FireFox 3.5 (приватный серфинг, новый javascript движок, новые свойства CSS 2.1 и 3, нативный JSON, фоновое выполнения javascript, querySelectors и querySelectorsAll, cross-site AJAX)
С нетерпением жду появления новой версии лисы в репозиториях ubuntu.
Что до php, то не порадовало использование разделителя '\" для пространств имен (всё-таки надеялся что будет нечто более привычное "::" или ".") к остальным нововведениям буду тоже присматриваться, все-таки надеюсь в скором времени пополнить ряды ZCE...
6.30.2009
6.05.2009
Google Page Speed
Ответ от гугля на яховский yslow в виде расширения для FireFox интегрирующегося в FireBug: http://code.google.com/speed/page-speed/
Создалось впечатление что информации выдает несколько больше чем yslow.
Создалось впечатление что информации выдает несколько больше чем yslow.
5.26.2009
nginx 0.7 stable
Буквально вчера ветка 0.7.х http-сервера nginx была обьявлена как stable, что не может не радовать =). Впринципе она довольно давно используется на одном посещаемом сайте и проблем с ней замечено небыло.
Среди заявленных нововведений (по сревнению с предыдущей stable веткой):
Собственно эти двум нововведением и их совместном использовании и будет посвящен дальнейший текст.
Чего хочется? Хочется сследующего:
Среди заявленных нововведений (по сревнению с предыдущей stable веткой):
- кэширование проксированных и FastCGI-серверов;
- директива try_files;
- поддержка выделений в регулярных выражениях в директивах location и server_name и ссылок на эти выделения во всех директивах, поддерживающих переменные, например, в директиве alias;
- два фильтра — XSLT и преобразования изображений;
- предварительная поддержка IPv6;
- nginx/Windows.
Собственно эти двум нововведением и их совместном использовании и будет посвящен дальнейший текст.
Чего хочется? Хочется сследующего:
- ресайзинг изображений не на application-level, а на server-level (в любой момент можно сгенерировать тумбнайл необходимого размера, причем это будет сделано "по запросу")
- контролированое (в разумных по времени пределах) кэширование полученных тумбнайлов на frontend-серверах
- backend-сервер изображений (ресайзит оригинальны)
- frontend-сервер thumbnail'ов (сохраняет у себя в кэше)
http {
proxy_cache_path /var/nginx/cache levels=1:2 keys_zone=thumbnail:10m;
...
# backend dynamic resizing
server {
listen *:80;
server_name i175d.site.domain;
root /var/www/site.domain/public_html/images;
location / {
image_filter_jpeg_quality 95;
image_filter crop 175 120;
}
}
# сервер thumbnail'ов
server {
listen *:80;
server_name i175.site.domain;
location / {
proxy_cache thumbnail;
proxy_cache_valid 60m;
proxy_pass http://i175d.site.domain;
}
}
}
Отдача статического изображения напрямую:#ab -n 1000 -c 100 http://i.site.domain/image_static.jpg
Concurrency Level: 100
Time taken for tests: 0.144 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 13765478 bytes
HTML transferred: 13544630 bytes
Requests per second: 6942.18 [#/sec] (mean)
Time per request: 14.405 [ms] (mean)
Time per request: 0.144 [ms] (mean, across all concurrent requests)
Transfer rate: 93322.66 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 4 1.5 3 8
Processing: 3 10 4.0 9 20
Waiting: 2 7 3.5 6 15
Total: 5 14 4.6 13 25
Ресайзинг без кэширования (закоментированы proxy_cache_valid и proxy_cache):#ab -n 1000 -c 100 http://i175.site.domain/image.jpg
Concurrency Level: 100
Time taken for tests: 13.863 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 13389000 bytes
HTML transferred: 13175000 bytes
Requests per second: 72.13 [#/sec] (mean)
Time per request: 1386.347 [ms] (mean)
Time per request: 13.863 [ms] (mean, across all concurrent requests)
Transfer rate: 943.14 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 3 8.5 0 32
Processing: 58 1275 602.5 1187 3303
Waiting: 39 1274 602.5 1187 3302
Total: 71 1277 603.2 1189 3303
С вкюченным кэшированием (1-й запуск)#ab -n 1000 -c 100 http://i175.site.domain/image.jpg
Concurrency Level: 100
Time taken for tests: 1.617 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 13367000 bytes
HTML transferred: 13175000 bytes
Requests per second: 618.55 [#/sec] (mean)
Time per request: 161.670 [ms] (mean)
Time per request: 1.617 [ms] (mean, across all concurrent requests)
Transfer rate: 8074.31 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.9 0 8
Processing: 8 160 335.3 20 1502
Waiting: 8 160 335.3 20 1502
Total: 8 160 336.5 20 1506
С включенным кэшироваием (2-й запуск):#ab -n 1000 -c 100 http://i175.site.domain/image.jpg
Concurrency Level: 100
Time taken for tests: 0.151 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 13367000 bytes
HTML transferred: 13175000 bytes
Requests per second: 6601.23 [#/sec] (mean)
Time per request: 15.149 [ms] (mean)
Time per request: 0.151 [ms] (mean, across all concurrent requests)
Transfer rate: 86170.50 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 4 4.0 3 17
Processing: 2 10 4.6 9 21
Waiting: 1 7 3.9 7 19
Total: 5 14 6.3 11 34
Как видно по результатам отдача закэшированного изображения происходит практически с такой же скоростью как и отдача статического файла напрямую. Большим плюсом в такой схеме является то, что nginx сам следит за устареванием кэша и чистит его по истечении заданного в конфиге времени.
Ярлыки:
nginx
5.12.2009
Python code completion в gedit
Небольшая комманда для установки необходимых плагинов:
После этого в настройках gedit включаем плагины "Python Code Completion" и "Word Completion"
#!/usr/bin/env bash
cd ~/.gnome2/gedit/plugins && \
curl -L http://github.com/fenrrir/geditpycompletion/tarball/master > pycompletion.tar.gz && \
tar xzf pycompletion.tar.gz && \
rm pycompletion.tar.gz && \
rm -Rf ./fenrrir-geditpycompletion* && \
git clone git://github.com/fenrrir/geditpycompletion.git && \
mv geditpycompletion/* . && \
rm -Rf ./geditpycompletion && \
wget http://users.tkk.fi/~otsaloma/gedit/completion.gedit-plugin \
wget http://users.tkk.fi/~otsaloma/gedit/completion.png \
wget http://users.tkk.fi/~otsaloma/gedit/completion.py
После этого в настройках gedit включаем плагины "Python Code Completion" и "Word Completion"
4.28.2009
Отправка rss/atom лент на почту
Давно хотел взяться за изучение python'a, но всё как то ноги не доходили, а тут по работе потребовалось написать софтику по отправке rss ленты по базе email'ов. Собственно после недолгого анализа требований и исходя из подручных средств отсановился на python.
В результате получилась небольшая функция feed2mime которая и занимается получением ленты новостей, преобразованием её в html, дальнейшим разбором средствами html5lib для нахождения изображений и последующим их внедрением в тело сообщения. На выходе - MIMEMultipart который можно рассылать уже с помощью smtplib.
В результате получилась небольшая функция feed2mime которая и занимается получением ленты новостей, преобразованием её в html, дальнейшим разбором средствами html5lib для нахождения изображений и последующим их внедрением в тело сообщения. На выходе - MIMEMultipart который можно рассылать уже с помощью smtplib.
#!/usr/bin/env python
"""
Convert RSS/ATOM feed in HTML'ed MIMEMessage (with images embedding)
"""
import urllib2, feedparser, smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
from html5lib import HTMLParser, treebuilders, sanitizer
from html2text import html2text
from hashlib import md5
def feed2mime(url, decorator, limit):
feed = feedparser.parse(url)
msgRoot = MIMEMultipart('related')
msgAlternative = MIMEMultipart('alternative');
msgRoot['Subject'] = feed.feed.title
msgRoot.preamble = 'This is a multi-part message in MIME format.'
html = decorator.get(feed.entries, limit)
_md5 = md5();
parser = HTMLParser( tree=treebuilders.getTreeBuilder("dom"), tokenizer=sanitizer.HTMLSanitizer )
dom = parser.parse(html)
i = 0
_images = [];
for node in dom.getElementsByTagName('img'):
i += 1
if node.hasAttribute('src'):
_md5.update(node.getAttribute('src'))
cid = _md5.hexdigest()
try:
url = urllib2.urlopen(node.getAttribute('src'), timeout = 5)
try:
mimeImage = MIMEImage(url.read(), _subtype="jpg");
except Exception, e:
pass
url.close();
mimeImage.add_header('Content-ID', '<' + cid + '>')
node.setAttribute('src', 'cid:' + cid)
_images.append(mimeImage)
except Exception, e:
print "[", i, "] ", e, "\n"
msgAlternative.attach(MIMEText(dom.toxml().encode('utf-8'), 'html', _charset="utf-8")) #, _charset="utf-8"
msgRoot.attach(msgAlternative)
msgRoot.attach(MIMEText(html2text(html).encode('utf-8')))
for i in _images:
msgRoot.attach(i)
return msgRoot;
if __name__ == '__main__':
import getopt, sys
opts, args = getopt.getopt(sys.argv[1:], "", ["url=", "smtp-host=", "smtp-user=", "smpt-pass=", "limit=", "from=", "to="])
smtp = smtplib.SMTP()
smtpUser = False
smtpPass = False
iLimit = 10
sUrl = False
for o,a in opts:
if o == "--smtp-host":
smtp.connect(a)
elif o == "--smtp-user":
smtpUser = a
elif o == "--smtp-pass":
smtpPass = a
elif o == '--url':
sUrl = a
elif o == '--from':
sFrom = a
elif o == "--to":
sTo = a
elif o == "--limit":
iLimit = int(a)
class FeedDecorator:
def get(self, entries, limit):
html = ''
i = 0;
for entry in entries:
if i>=limit:
break;
html += '<p style="clear:both">'
html += '<b><a href="' + entry.link + '" target="_blank">' + entry.title + '</a></b><br />'
if(len(entry.enclosures) > 0):
html += '<img src="' + entry.enclosures[0].href + '" align="left" hspace="5" vspace="5"/>'
html += entry.description + '</p>'
i += 1
return html
msg = feed2mime(sUrl, FeedDecorator(), iLimit)
if (smtpUser and smtpPass):
smtp.login(smtpUser, smtpPass)
msg.__delitem__('From')
msg.__delitem__('To')
msg['From'] = sFrom
msg['To'] = sTo
smtp.sendmail(sFrom, sTo, msg.as_string())
smtp.quit()
Подписаться на:
Сообщения (Atom)

