Индексы и селективность (PostgreSQL)

Индекс по полю в БД потенциально может ускорить SELECT операцию с условием по данному полю, может ускорить заброс вида: ORDER BY поле LIMIT 20, но индекс замедляет существенно операции изменения таблицы и т.п.

Когда нужен индекс, когда он поможет и будет использован при SELECTах? Всё зависит от селективности индекса, т.е. от кол-ва строк, которые мы получим если зададим условие

проиндексированное_поле = значение

Отличный кандидат для индексирования - селективность 1, т.е. уникальный индекс (например, id), когда по указанному значению мы найдем максимум одну запись. Хорошо, когда селективность составляет

Зачем нам нужны высокоуровневые языки прогаммирования?

Наткнулся на чудесный пост от Moshe Zadka. Почему мы пишем программы сегодня на Python, Ruby, PHP, а не на старом добром Си? Почему используем заведомо менее эффективные (как по памяти, так и по скорости языки программирования).

Если кратко, Moshe приводит следующие доводы:

  • не все могут писать на Си, многим это просто недоступно, но это даже хорошо, если становится больше программистов - больше программ, больше удововлетворения для общества;

  • на языке высокого уровня писать быстрее - быстрее выпустим продукт на рынок, следовательно опередим конкурентов;

  • слишком много ошибок в программах на Си, которые можно избежать в языках высокого уровня;

  • люди готовы поменять деньги, вложенные в более мощное железо, на более "умные" программы.

Мне кажется, что вообще вопрос разработки на хороших языках высокого уровня не только быстрее, но и качественнее. Я думаю, что отсутствие в Си и Си++ прямо в самом языке так необходимых типов данных (хеши, списки и т.п.) приводит к неправильному мышлению начинающих программистов, они неправильно кодируют алгоритмы, получаются всё равно менее эффективные программы. А хороший язык высокого уровня уже в tutorial приучает читающего к правильному использованию структур данных, даёт сразу много готовых алгоритмов. Конечно, STL в Си++ решает несколько эту проблему, но даже Страуструп рассказывает о ней в отдельной главе, а часть книги предлагает заново написать тип строк и т.п.

Выступление на РИТ-2008

На конференции РИТ-2008 буду выступать с докладом "Сервер Flash-вещаний (RTMP) на Python или создание высоконагруженных сетевых серверов с использованием Twisted", буду рассказывать о сервере вещаний, который работает на Smotri.Com. Это будет в первый день, 14-го апреля в 16:40. Приглашаются все желающие. Материалы доклада ниже.

Видеозапись выступления

Слайды

Как преподавать C++?

Кого мы хотим подготовить, обучая студентов программированию на C++? Что они должны вынести из курса? Мне кажется, важно научить писать программы. Красивые, эффективные, сопровождаемые. Язык - лишь инструмент программирования. И надо научиться пользоваться инструментом. Вот когда в автошколе учат вождению машину, совсем не обязательно знать тонкости устройства шины CAN, обеспечивающей связь всех устройств автомобиля. Да, надо узнать, что такое тормоза, руль, двигатель, но на каких-то деталях надо остановиться, и, самое, главное, надо научиться пользоваться автомобилем (то есть водить автомобиль) безопасно, уверенно и т.п.

А почему мы заставляем студентов знать подробности языка, которые нельзя продемонстрировать на разумном примере? Например, множественное наследование (я уже молчу о виртуальном наследование в сочетании с множественном). Для этого нужны примеры, большие примеры, огромное количество понятий (например, интерфейсы), чтобы студент почувствовал, что и зачем. А мы с упорством сумасшедших рассказываем о том, какие члены классов будут видны или не видны в той или иной ситуации.

Вот объясните мне, кто-нибудь использовал перегрузку наряду с виртуальностью?

class A
{
public:
    virtual int f();
};
class B : public A
{
public:
    virtual int f(double);
};

Что это нормально, это работает? Зачем нужны эти знания? А кто перегружал функции, расположенные в разных областях видимости?

class A
{
    void f(char);
public:
    void f(int);
};

A a;
a.f('a');

Ну кто такое делает в реальных задачах? Зачем студентов заставлять разбирать эти примеры?

Как я понял из интервью Бьерна Страуструпа, это проблема преподавания Computer Science не только на факультете ВМиК МГУ. Он говорит, кого мы готовим? lanugage lawyers? По-моему, это очень точно английское словосочетание... Мы готовим студентов стать членами комитета ISO по стандартизации C++?

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

Кому это нужно? Самоудовлетворение от задалбливания в умы студентов бесполезных знаний?

Почему мы не экзаменуем их на умение программировать? Ну или хотя бы на знание базовых конструкций языка? Зачем такие извращенные примеры?

Если бы я опубликовал весь вариант работы, которую писали студенты, думаю, многие были бы в шоке. Я уверяю, что подавляющее большинство потрясающих, талантливых C++-программистов не смогут решить этот вариант на "пять". Но от этого они не становятся хуже, а претензии надо предъявлять тем, кто составил такую программу курса, предъявляет такие требования к студентам. Как они могут полюбить такой предмет?

По-моему, пора остановиться и сменить ориентиры.

Релиз 12-й версии LoadUp

Обо всех новоовведениях расскажут модераторы. О видимых и заметных для пользователей. Мы на пути оптимизации, выжимая всё до последней капли из каждого SQL-запроса и каждой PHP-конструкции. Самое главное впереди - оптимизация, всё должно работать быстрее с точки зрения каждого конечного пользователя.

Час Икс - ночь с 26-го на 27-е марта.

Озарение программисткое

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

И потом хоп... и озарение!

Поиск несуществующего memory leak

Очень забавная история. Был работающий и написанный сервер вещаний (a-la Red5) на Python. В связи с развитием основной класс - класс протокола - был разрезан на несколько более мелких классов, которые собирались вместе множественным наследованием в единый монолит, который должен был по функциональности повторять исходный класс (до рефакторинга). Как показало вскрытие, старая версия стабильно работает неделю за неделей, а новая версия через неопределенный, но достаточно короткий период времени (несколько часов) откушивает всю доступную память и погибает.

Типичная ситуация для memory leak, причём опытным путём стало понятно, что эта утечка как-то коррелирует с нагрузкой на сервер (что логично), но зависимость неоднозначная. Момент появления утечки был сужен до одного коммита - казалось бы дело за малым. Анализ исходников в поисках того момента, когда была внесена утечка ничего дает - исходники испаханы вдоль и поперек. Ничего.

Анализ во время выполнения с помощью с помощью довольно замысловатых утилит из этого поста

ни к чему не привёл - нет ничего. Я пробовал считать количество объектов, которые видит модуль gc в питоне (то есть тех, кто поддерживает garbage collection), но количество не растет существенно и пропорционально нагрузке на сервер. Однако память процесс кушает и довольно быстро.

В проекте было расширение, написанное на Си, - его анализ, исправление мелких неточностей результата не дает.

Остается неутешительный вывод - в силу того, что число объектов в программе не растет, то значит либо растет размер каких-то объектов (например, строк путем конкатенации), либо это какая-то бага в Python, ОС или где-то еще.

Последнее выглядит романтично и привлекательно, но на самом деле ничего не дает - такую ошибку еще тяжелее найти и поправить, однако багтрекеры FreeBSD, Python и Twisted молчат по поводу таких ошибок.

Двигаемся дальше - создается тестовый клиент вещаний, который имитирует нагрузку на сервер: разное количество вещаний, авторы, подписчики вещания, различные ошибочные ситуации, чат. Тест, запущенный локально с локальным сервером (а нелокально тестовое окружение собрать тяжело - поток порядка 50-100 Мбит/с) не дает результатов - никаких следов утечки памяти ни за час, ни за два.

Отчаяние, практически неделя потерянного впустую времени, тестирование различных вариантов... Что еще? Есть еще Twisted-Conch+Twisted-Manhole - живая консоль с интерпретатором питона в работающем сервере. Но и она не дает никаких результатов - garbage collection работает, никаких разумных объектов, которые могли бы дать утечку памяти нет.

Озарение как всегда приходит в тот момент, когда его совсем не ждешь: ведь сервер вещает, то есть получает на вход поток в 0,5 Мбит/с, раздает его 200 клиентам и делает на выходе 100 Мбит/с, если у кого-то из этих 200 клиентов канал меньше по ширине 0,5 Мбит/с, то данные в буферах процессах начнут скапливаться. Для этого есть решение - дроп пакетов, он был реализован и работал...

Эврика! После разделения большого класса на кучу мелких фрагментов некоторые методы "разрезались" на части. И в них надо поставить вызов метода предка, чтобы все "куски" метода отработали, как и раньше. Но ведь в питоне есть еще MRO (Method Resolution Order), и надо отвыкнуть от того, что базовый класс в моём ощущении является последним в цепочке, то есть у него нет super(Klass, self) - он есть! Просто метод, который включал анализ буфера записи, который в свою очередь вовремя включал механизм пропуска пакетов отключился. И хотя всё работало, но пропуск пакетов не включался и буферы записи росли неограниченно. Исправление в одной строке - вызова метода предка решило проблему. Обидно :)

C++, просто смешно...

Что выведет данный код?

#include <stdio.h>

struct A
{
    A(int x = 3) { printf("%d\n", x); }
};

struct B: virtual public A
{
   B() : A(4) {}
};



struct C: virtual public A
{
  C() : A(5) { }
};

struct D: public B, public C
{

};

int main()
{
    D d;
    B b;
    C c;

    return 0;
}

Ответ:

3
4
5

Что самое смешное, можно из D::D() явно вызвать конструктор A с другим параметром. Наслаждаемся в C++ смесью виртуального наследования, раздельной компиляции и полученной кривости.

Contents © 2015 Andrey - Powered by Nikola