gns_ua: (Default)
А расскажите за эту вашу оопню. Есть класс Cup, обеспечивающий некоторый контейнер. Из содержимого контейнера строится объект класса Coffee. То есть в некотором смысле Cup содержит Coffee. Но, с другой стороны, верно и что Coffee налито в Cup.

Как идеологически правильно:

а) cup.coffee = Coffee(...)

Чашка знает где достать порошок, и пусть сама думает, как его заваривать.

б) coffee.cup = Cup(..)

И пусть кофе само дальше заваривается, используя чашку.

в) controller.cup = Cup(...)
controller.coffee = Coffee(...)

Попросим кофе сериализоваться и покажем чашке:

coffeestring = controller.coffee.toString()
controller.cup.put(coffeestring)
gns_ua: (Default)
If the task has a max_retries value the current exception will be re-raised if the max number of retries has been exceeded.

@celery.task
def test_retry(max_retry=5):
    print test_retry.request.retries
    raise test_retry.retry(countdown=1)


Угадайте, какое значение retries будет напечатано последним?

(no subject)

Sunday, 23 June 2013 18:04
gns_ua: (russe)
В питоне иногда особенно остро понимаешь, что всё это ваше ООП - просто design pattern, а эта ваша "поддержка ООП" - просто немного синтаксического сахара.
gns_ua: (russe)
Уже сто раз замечал, насколько удобнее, скажем:

- сидя на полу, поставив ноут на диван

или

- забравшись на диван с ногами, ноут на коленях

или даже

- стоя на кухне, ноут на холодильнике

То есть вот админские задачи, или там, переписка всякая, оно конечно и за столом вполне ок. А вот именно писать код за столом довольно мучительно. Существенная часть неких внутренне-инфраструктурных вещей была придумана и реализована как раз в одной из этих нелепых поз.

С вами этого не бывает?

одиссей

Thursday, 31 January 2013 23:18
gns_ua: (russe)
Чота наслушавшись Pulse малоизвестных британцев Pink Floyd, дёрнуло меня вытащить Odyssey One Compilation девяносто шестого года. Давненько не слушал. И оно неиллюзорно клёво.

Собственно, вот, с трека #03 Venus Rapsody и до #07 Prophet of Evil включительно, двадцатиминутный кусок, - это одно из самых прекрасных мест вообще во всей музыке, которую слышал.

Кроме того, это весьма и весьма атмосферненько для ночной работы.

Вторая штука, котируемая на том же уровне - это фигурно порезанный Dreamland Майлса.

Да, у меня есть претензии к композиции альбома. Я слушаю его в таком виде:

Треклист от gns )

Честно, никогда не понимал, за каким хером после In my dreams вхерачили вокальный One and one, и терпеть не могу вокальную версию Fable.

(no subject)

Tuesday, 15 January 2013 10:09
gns_ua: (russe)
Вот оно чо.

[altlinux@eeelive ~]$ python -c 'import redis, time; r=redis.Redis(); p=r.pipeline(); p.watch("abc"); p.set("123", 1); time.sleep(5); p.execute()'

В monitor видно, что херню делает:

1358237927.046987 [0 127.0.0.1:51442] "WATCH" "abc"
1358237927.048088 [0 127.0.0.1:51442] "SET" "123" "1"
1358237932.053436 [0 127.0.0.1:51442] "MULTI"
1358237932.053582 [0 127.0.0.1:51442] "EXEC"
1358237932.054853 [0 127.0.0.1:51442] "UNWATCH"


Зато вот такое, без вотча:

$ python -c 'import redis, time; r=redis.Redis(); p=r.pipeline(); p.set("123", 1);time.sleep(2); p.execute()'

Делает:

1358237753.861087 [0 127.0.0.1:51420] "MULTI"
1358237753.861234 [0 127.0.0.1:51420] "SET" "123" "1"
1358237753.861319 [0 127.0.0.1:51420] "EXEC"


Всё правильно. Тогда какого?

Можно сперва запайпить, а потом уж ставить вотч и экзекать. Это работает:

$ python -c 'import redis, time; r=redis.Redis(); print r.get("abc"); p=r.pipeline(); p.set("abc", 1); p.watch("abc"); time.sleep(5); p.execute(); print r.get("abc");'
None
1
===============================
1358238142.575640 [0 127.0.0.1:51474] "GET" "abc"
1358238142.577093 [0 127.0.0.1:51474] "WATCH" "abc"
1358238147.579733 [0 127.0.0.1:51474] "MULTI"
1358238147.579892 [0 127.0.0.1:51474] "SET" "abc" "1"
1358238147.579977 [0 127.0.0.1:51474] "EXEC"
1358238147.581572 [0 127.0.0.1:51474] "UNWATCH"
1358238147.582558 [0 127.0.0.1:51474] "GET" "abc"


И я бы даже смирился, да вот беда - их собственный враппер делает сначала watch, а потом отдаёт пайп для работы:

Read more... )

(no subject)

Tuesday, 27 November 2012 21:00
gns_ua: (Default)
Дебажил я распределённый код. Дебажил-дебажил, читал-перечитывал, в конце концов плюнул на всё и вкрутил мегаизбыточное логирование проходящих данных на каждом шаге обработки, туда же всякие проверки-хуерки, и запустил всё это, предвкушая как сейчас точно локализую проблему.

И случилось страшное. Ошибки перестали появляться.
gns_ua: (Default)
На тридцать первом году жизни и двадцатом программирования, со мной случилось это.

Глядя на собственный говнокод такого типа:

def getitems(workers):
    items = []
    for w in workers:
        items.extend(get_worker_items(w))
    return items


- я вдруг перестал понимать, зачем вся эта унылота и почему не сделать просто:

def getitems(workers):
    for w in workers:
        for i in get_worker_items(w):
            yield i


Ведь дальше-то этот лист большой опять кто-то будет сканить, опять формировать новый лист, опять кому-то отдавать. Так зачем? Пусть вся йилдят! Корутины! А в промежутках каждый, возможно, успеет ещё что-нибудь где-нибудь отметить, что тоже хорошо.

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

И вроде ж знаешь уже много разных вещей, - серьёзно занявшись программированием после нескольколетнего перерыва, ничего, впрочем и к сожалению, не отнявшего от предварительного пути бейсик=>паскаль=>фокспро=>qt=>пхп (шелл сюда не включаю по ряду очевидных причин). Но вот чтоб сразу мыслить в этих терминах...

(no subject)

Tuesday, 19 June 2012 19:09
gns_ua: (Default)
"Тут просто код немножко по-дебильному написан"

(no subject)

Friday, 30 March 2012 14:51
gns_ua: (Default)
> задача о разработке метода определения делимости числа на 15, при условии, что запись числа настолько длинная, что не влезает ни в один целочисленный тип (т.е., грубо говоря, делить напрямую нельзя).

http://smartsourcing.ru/blogs/kurilka/1364

Очевидно, что необходимо и достаточно выполнение двух условий:

а) последняя цифра 5 или 0

б) сумма цифр (aka X mod 9) делится на три. Свойста этой штуки таковы, что на самом деле полную сумму считать не нужно: достаточно складывать цифры по одной, и как только результат становится двузначным - останавливаться, делить на 9 с остатком, продолжать.

def mod9(n):
    sum = 0
    for x in n:
        sum+=int(x)
        if sum>20: sum = sum % 9
    return sum

# x задано как строка
if x[-1] in ('0', '5') and mod9(list(x)) % 3 == 0:
    print "yes'
else:
    print "no"


(вообще, порог 20 здесь произвольный. Можно и 100 взять - чтоб не слишком часто делить)
gns_ua: (Default)
Вдруг осознал что изобретаю типа-монады на твистеде.
gns_ua: (Default)
И вдруг внезапно обнаружил, что три месяца назад зачем-то написал

return reactor.callInThread(queue.push, (channel, message, time.time()))

Вместо return queue.push((channel, message, time.time()))

Учитывая как именно устроена очередь и что она делает, результат не заставил себя ждать.

(no subject)

Wednesday, 28 December 2011 22:57
gns_ua: (Default)
сижу вот это, ковыряюсь с среднеквадратичными и прочими экспоненциальными скользящими, да и думаю что надо было тот семестр статистики досидеть всё же. Чтоб представлять, что как, чего на самом деле можно ожидать, и какие артефакты могут вылезти.

Хотя, с другой стороны, сотрудники неподалёку честно учили, но им на данный момент вся эта байда кажется ещё более мутной чем мне. Оно ж когда понадобится, а бывает это не так часто, тут и оказывается что эээ, ммм, вроде чота десять лет назад слышал :)

Ну и я "слышал".

Итак. Есть некоторый цикл, в котором происходит нечто. Интересно время исполнения этого цикла и длительность его отдельных этапов. То есть, по окончании каждой итерации имеем набор (total=27.3, stage1=20.17, stage2=6.43, stage3=0.02, stage4=0.63). Некая штука время от времени запрашивает эти циферки. Существенно реже, чем происходят сами итерации (по наблюдениям, одна итерация может занять от 10 до 40 секунд).

Я бы с удовольствием напрямую пушил в момент окончания циферки с таймстампом, но давайте попробуем обойтись без этого. При таком раскладе, конечно, мы часть информации теряем, и это ок. Главное, не потерять что-нибудь важное и интересное (~ общие тренды + аномалии).

Опуская всю проведённую теоретическую и экспериментальную исследовательскую работу, схема такова:

- тайминг каждой итерации записывается в кольцевой буфер размером 5.

- при этом сразу записывается в специально отведённое место пара (ring[-1], qaverage(ring, exp)) - значение из последней итерации и среднеквадратичное взвешенное по e^i:

def qaverage(ring, weight_function = lambda x: 1):
  s = sum([ring[i]*ring[i]*weight_function(i) for i in xrange(len(ring))])
  d = sum([weight_function(i) for i in xrange(len(ring))])
  return sqrt(s/d)

То есть, значимость самых новых элементов больше.

На графике рисуется это самое значение и соответствующее ему qaverage (очевидно, бегающее где-то около, выше или ниже, самого значения). Из постановки задачи ясно, что бОльшая часть этих пар будет благополучно профачена - забирается консумером, грубо говоря, каждая n-я при случайном n из [2,7].

То есть общее состояние "примерно" видно. Конкретные высокие значения могут никогда не попасть в график, но оставят след в qaverage, хотя сам qaverage конечно их никогда не достигнет только если все пять последних будут одинаковые. В принципе, их можно будет ручками посмотреть в логе :) И понятно, что если qaverage больше выхваченного значения, то до него были цифры выше, и наоборот. На самом деле я бы увеличил длину буфера до 10, и показывал дополнительно qaverage от (последней) половины сохранённых данных. Или можно обойтись одним числом (каким)?

В общем, природа данных известна, граничные условия известны - ругайте :)

ЗЫ. Вопросы вида "почему среднеквадратичное?" и "почему e^i?" лучше формулировать в виде "надо использовать XXX потому что А, B, C".

ЗЗЫ. C реализацией exponential moving average возиться пока не стал ибо не уверен что есть смысл.
gns_ua: (Default)
Однажды тимлид собрал митинг и говорит: «А что, девелоперы, не деплоил ли из вас кто-нибудь на продакшен?» Все сказали: «Нет». Джуниор Ваня покраснел как рак, и сказал тоже: «Нет, я не деплоил».

Тогда тимлид сказал: «Что кто-нибудь из вас задеплоил прод и не признаётся, это нехорошо; но не в том беда. Беда в том, что в предпоследнем коммите есть недоделанный кусок, и если кто задеплоил его, то консистентность базы нарушится. Я этого боюсь».

Джуниор Ваня побледнел и сказал: «Нет, я тот коммит откатил».

И все засмеялись, а Ваня заплакал.
gns_ua: (Default)
Похоже, в архитектуре я немного лажанулся.

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

Беда в том, что цикл сэмплирования меньше цикла обмена примерно в два раза (примерно.... не менее чем в два). Это так и задумано, по ряду причин, и это не проблема когда мы берём циферки как таковые. Но когда мы считаем дельту/время - с одной стороны, ловятся короткие пики, которые на бОльшем интервале усреднения смазались бы. Это бы хорошо, но, с другой стороны, дельты 60/0/60/0 на вдвое бОльшем интервале дали бы 30/30, а реально сервер может выхватить из них 0/0. Или вообще один сэмпл 60, тут вам не риалтайм и не очереди.

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

Можно вот что, можно в коллекторе взвешенное скользящее среднее сделать. Так даже прикольнее получится.
gns_ua: (Default)
Сохранить и перечитать при случае

http://habrahabr.ru/blogs/python/114576/
http://habrahabr.ru/blogs/python/114585/
http://habrahabr.ru/blogs/python/114587/
http://habrahabr.ru/qa/4847/#answer_20947

Помню, в децтве книжка про смолтолк выносила мне мозги своими : Metaclass, абстрактный суперкласс всех метаклассов, сам является экземпляром класса class, который в свою очередь, является его подклассом :]
gns_ua: (Default)
Задача 2. Определить, является ли введённая строка палиндромом («перевёртышем») типа ABBA, kazak и пр.

Постановка задачи: Требуется сравнивать попарно символы с начала и с конца строки S (первый и последний, второй и предпоследний и т.д.). Если в каждой такой паре символы одинаковы, строка является палиндромом. Соответственно, каждая проверка пары символов должна получить некоторый признак ( flag — «флаг»), который будет равен 1, если символы в паре совпадают и 0, если не совпадают. Окончательный результат обработки строки получится как произведение всех значений «флагов». Если хотя бы один раз «флаг» оказался равен нулю, строка палиндромом не является и произведение всех «флагов» окажется равным 0. Количество пар не превышает половины длины строки L (точно равно половине длины для строк с чётным количеством символов и результат целочисленного деления длины строки на 2 для строк с нечётным количеством символов, поскольку «центральный» символ строки с нечётным количеством символов очевидно совпадает сам с собой).

[блаблабла, код на псевдоязыке, код на питоне]

Однако использование особенностей строк в Python, их функций и методов, позволяет решить эту задачу более изящно. Например, так.

# -*- coding: utf-8 -*-
#
s1=raw_input('Исходная строка:')
lst=list(s1)
lst.reverse ()
s2=' '. join(lst)

if s1==s2:
    print 'Палиндром'
else:
    print 'Не палиндром!'

Здесь исходная строка преобразуется в список, затем список «переворачивается» и из него с помощью пустой «строки-объединителя» формируется новая строка. Затем строки сравниваются. Цикл оказывается не нужен! Всю работу делает Python.


http://www.altlinux.ru/news/archive/2011/01/item/624/ [via http://www.linux.org.ru/news/doc/5866584]

Нечего сказать, изящненько, /me закрывает лицо рукой

(no subject)

Thursday, 1 December 2011 01:03
gns_ua: (Default)
Итоги подведём:

$ git log --stat --since 'Nov 30' | grep Date | tail -1
Date: Wed Nov 30 12:29:21 2011 +0200

$ git log --stat --since 'Nov 30' | grep Date | head -1
Date: Thu Dec 1 00:43:36 2011 +0200

$ git diff --stat $(git log --stat --since 'Nov 30' | grep commit | tail -1 | cut -d\ -f 2) Agent/ | tail -1
22 files changed, 357 insertions(+), 270 deletions(-)

Допилил два больших куска, вокруг/ради них немного порефакторил, ничего при этом не сломав, и оттестировал на двух платформах.

gns умный, gns теперь может взять баночку пива или даже две и вызвать такси. Чота заебался немножко.

Profile

gns_ua: (Default)
gns_ua

April 2017

M T W T F S S
     12
3456789
10111213141516
17181920212223
24252627282930

Expand Cut Tags

No cut tags

Style Credit