B Gata H Kei

Э-э…….

Сюжет: обычная японская школьница хочет переспать со ста парнями. Для начала хоть с одним. Но у неё сдвиги в башке (внезапно!), и поэтому красивых парней она стесняется и тренируется на каком-то generic japanese guy. Наверняка, в него потом влюбится.

Всё это было бы обычной рабу-коме, если бы не чокнутая вводная про сто парней. Из-за неё типичные романтические клише обретают, я бы сказал, новую мелкоту. Они втрое глупее обычного! “А сейчас я его завалю. Ох завалю! Ой! Он смотрит на меня! Что делать? Что делать?!”
Естественно, никого в первой серии героиня не завалила, и, подозреваю, так и продолжится.

В целом довольно тупенько. Чем-то напоминает хомяка Эбитю и Докуро-тян.

Дурарара 13

– Шила в мешке не утаишь, Изая!
– В доме покойника не говорят о верёвке, Симон!

Русские диалоги такие русские.

Новые оп и ед.

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

Грр

Как же меня бесит философия! Я столько могу сделать, могу переводить, писать, программировать, даже в диаблу играть, могу образовываться в какой-то полезной области. Ладно, я на мехмате, я даже математикой могу заниматься. Но какого чёрта! Вместо этого я сижу и продираюсь мозгами сквозь какую-то мутотень, которую одни от нечего делать сочинили, другие не смогли нормально перевести, а третьи заставляют меня читать, и, не понимая, отвечать!

Да кому это нужно?

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

Хоть одного голодного философия накормила? Хоть одну работу упростила? Хоть кому-нибудь жизнь облегчила? Нет! Это пустой трёп. Каждый “философ”, не поняв других, рвётся написать своё, потом сто раз меняет мнение и переписывает, и всё пихает под одним именем, так что уж никто вконец не может понять, на чём же, и зачем же, он в итоге остановился.

И все вежливо, как английские дворецкие, кушают друг у друга эту овсянку, и с вытянутыми лицами объявляют: “я тут у вас немножечко не понял, но история клёвая, сэр”.
Да голый ваш король!

О философии

Философия отличается от Библии тем, что в ней больше книг.

Ололо

Лектор по русскому разослал всем письмо, в котором сообщил, что для допуска к зачёту нужно пройти тест из 60 вопросов на его сайте. “Пробовать можно только один раз, кто не пройдёт – допущен не будет”.

Через три дня лектор по философии (!) разозлал всем правильные ответы на тест по русскому, с припиской: “занимайтесь лучше философией”.

Приезжали товарищи из ii-subs, намахали вместе 18 км по Москве.

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

Всё так близко.

Bachelor of Science

В Америке оканчивающие вуз получают степень Bachelor of Science, или “Бакалавр наук”, сокращённо BS. В разговоре это используется так:
“I just got my BS in philosophy and I’m looking for a work”
“Try Mac, they’re always hiring”

Удобно, что BS – это также известное сокращение для bullshit, что примерно значит “пустой трёп”, “чушь собачья”.

Bonus track. Также в английском языке популярно слово “major”, которое в качестве глагола значит “специализироваться” или “получать высшее образование в области”:
“I decided to major in literary arts… Am I going to have trouble finding work?”
“Yeah, all the burger seller positions are usually taken by philosophers”.

О паскале и объектах #2

Я написал предыдущий пост, и знакомый меня справедливо спросил, а какие же именно функции вызываются при создании объекта? Проверить несложно!
tmp := TObject.Create;
tmp.Destroy;

Оказывается, вот полный список всех вызовов при создании объекта: (далее)

Create
@ClassCreate
TObject.NewInstance
TObject.InstanceSize
@GetMem
TObject.InitInstance
@AfterConstruction
TObject.AfterConstruction

Из них TObject.InstanceSize и TObject.AfterConstruction не делают вообще ничего серьёзного, остальные не слишком много (20-30 инструкций).

Выглядит довольно безобидно! Как же на самом деле? Чтобы посмотреть, насколько быстро создаются объекты, я написал простенькую программу (pastebin). В ней в цикле создаётся и уничтожается 50 миллионов объектов и рекордов.
Для рекордов я использовал два варианта создания/удаления: GetMem/FreeMem и New/Dispose. Последний отличается тем, что Дельфи автоматически генерирует код, инициализирующий и очищающий так называемые “сложные” поля – строки и указатели на интерфейсы. Разумеется, Dispose не может быть быстрее FreeMem, поскольку в конечном счёте его же и вызывает!

Итак, пустой объект и пустой рекорд, результаты в миллисекундах:
Objects: 5469
Records through new/dispose: 344
Records through GetMem/FreeMem: 343

Неплохо! Объекты в десяток раз медленней! Однако у этого есть причина, которая станет ясна, если мы повторим эксперимент, добавив в объект и в рекорд по одному полю типа integer.

Теперь мы получаем:
Objects: 5453
Records through new/dispose: 1094
Records through GetMem/FreeMem: 1109

Откуда такой прирост у рекордов? Дело в том, что размер рекорда в прошлом эксперименте был равен нулю. GetMem/FreeMem просто игнорировала эти пустые запросы. У объекта же существуют скрытые поля. Если мы запросим размер объекта

tmp := TObject.Create;
writeln(‘Size: ‘+IntToStr(tmp.InstanceSize));

То получим:
Size: 4
Как только мы добавили поле и в рекорд, оптимизация GetMem перестала работать, и время создания записи подскочило в три раза. Но это ещё не всё! Добавим в рекорд поле типа string, чтобы проиллюстрировать разницу между New и Dispose.

Получаем:
Objects: 6188
Records through new/dispose: 3687
Records through GetMem/FreeMem: 1094

“Корректное” создание рекордов уже всего в два раза медленней объектов! Рекорды через GetMem/FreeMem работают с прежней скоростью, поскольку размер объекта не изменился: переменная типа string занимает те же четыре байта, что и integer.

Примерно то же получится, если добавить в рекорд динамический массив: он тоже требует финализации. А вот статические массивы не требуют: память для них выделяется за один запрос, вместе с памятью записи:
FField: array[0..40] of integer;
Objects: 6844
Records through new/dispose: 1188
Records through GetMem/FreeMem: 1187

Казалось бы, я совершенно напрасно ругал объекты! Ведь любой сколь-либо сложный набор данных в рекорде создаётся всего в два раза быстрее объекта. Ну, два раза для таких быстрых операций – это ерунда. Я уже готов был придти к такому выводу, как решил посмотреть, сколько занимает сложение строк:
s := s + ‘test’;
if Length(s) > 10000 then s := ”; //Чтобы не разбухала

1500 микросекунд! А разница между New и GetMem в примере со строкой была 2500!
Иными словами, расширение места под строку и копирование слова “test” занимает меньше времени, чем инициализация/финализация пустого поля типа string! Да как такое может быть?
Оказывается, вот как. Оказывается, для инициализации и финализации полей Дельфи вставляет не сам код, а вызов внутренних функций @New/@Dispose с параметром, в котором зашифровано, что именно удалять. Внутри этих функций довольно громоздкий процесс разборы параметра на части.

Попробуем сделать всё вручную! Напишем:
GetMem(rec, SizeOf(rec^))
pointer(rec.FField) := 0; //инициализация строки
rec.FField := ”; //финализация строки
FreeMem(rec);

Во-первых, дельфи могла бы догадаться, что на момент присваивания пустой строки rec.FField и так пустой. Но Дельфи этого, слава богу, не делает, и честно проверяет “if rec.FField<>nil then @LStrClr”, образно говоря. Таким образом, мы выполняем все операции, необходимые для создания/очистки рекорда со строковым полем.
Время? ~1300. Меньше, чем на 100 миллисекунд отличается от простого GetMem/FreeMem. Остальные 2400 микросекунд уходят на шатания по функциям @New/@Dispose с выяснением в рантайме вещей, которые и так известны на момент компиляции.

Теперь сделать решительный вывод опять стало сложно. Получается, если делать всё действительно оптимально – то есть, вручную – то рекорды примерно в шесть раз быстрее объектов – и этот разрыв будет расти с ростом сложности! Шестикратное замедление – это уже вполне значительная разница.
С другой стороны, если пользоваться для инициализации рекордов средствами Delphi (New/Dispose), то разница всего лишь в два раза, и она будет уменьшаться с ростом сложности! Ведь чем сложнее объект, тем большую часть создания занимает инициализация, а она общая у объектов и у New/Dispose рекордов.

Во всяком случае, вывод надо сделать такой: с рекордами не стоит использовать New/Dispose, это убивает весь их выигрыш в скорости. Если же вы используете New/Dispose, то уже не очень жалко превратить рекорды в объекты. Это уже мало (в пару раз) замедлит дело. Совершенно неожиданный вывод, поскольку я всегда считал New/Dispose быстрыми обёртками над GetMem/FreeMem.

Вообще же говоря, чтобы оценить порядок временных затрат: время на создание пустого TObject примерно равно одной десятитысячной микросекунды. В общем, я скорее всё же был неправ, обвиняя объекты в медлительности. Разумеется, было бы лучше, чтобы объекты создавались без дополнительной суеты, но её не так много, чтобы это делало их использование при большой нагрузке непрактичным.

О паскале и объектах

Знаю, что программистов тут мало, но хочется куда-то написать. Я вдруг понял, какой полезной возможности нет в Delphi, которая давно есть во всех компиляторах.

В ней нет объектов.

Конечно, есть классы, которые (далее)

почти объекты. Кроме того, что они тяжёлые. Создание класса – это вызов десятка функций, сотни проверок, несколько выделений памяти. По космическим меркам это всё, конечно, мелочи. По сравнению с поиском в какой-нибудь сотне тысяч записей или рендерингом какой-нибудь сложной фигуры цена создания класса – разменная копейка. На неё не стоит обращать внимания, говорит идеология Delphi.

Но это неправда.
Копейки очень быстро собираются в рубль. Классами нельзя играть с такой же лёгкостью, как рекордами. Их не жалко в ситуациях, которые возникают редко: при создании приложения, открытии окна, загрузке файла. Но при обслуживании запроса по сети? Уже нет. Создавать класс на каждый запрос – слишком дорого. А если их будет тысяча в секунду? А десять тысяч?

Остаётся использовать для таких задач рекорды. Но тогда пропадает вся полезность классов! Из объектов они превращаются в подобие неймспейсов: не воплощают функциональность элементов, а разделяют код.

Delphi очень нужны наследование и vtable рекордам. Ну или возможность сделать класс lightweight, чтобы он не вызывал всю эту борландовскую ерунду при инициализации. Чтобы стандартное Create было одним выделением памяти + занулениями, как с рекордом.

UPD: Эксперименты показали, что я в этом мнении более-менее неправ.