Pull to refresh
59
0
Семён Приходько @ababo

User

Send message

Доступный сервис транскрипции

Level of difficultyMedium
Reading time5 min
Views1.1K

Так вышло, что у меня образовалось некоторое количество свободного времени, которое мне захотелось потратить на небольшой хобби-проект, который, как надеюсь, даже имеет шанс превратиться в стартап. Идея была в том, чтобы создать очень доступный сервис транскрипции потока речи в текст. Я решил назвать его Blobfish, т.к. мне очень нравится внешний вид рыбы-капли. Только давайте без намёков на всем известный мем!

По моему мнению, конкурентоспособность подобного сервиса может определяться или исключительным качеством транскрибирования или же значительно более низкой, чем у конкурентов, ценою. К сожалению, ни мои компетенции, ни имеющиеся в распоряжении ресурсы не позволяли пойти по первому пути. Действительно, я планировал использовать компоненты, находящиеся в публичном доступе, потому на сногсшибательное качество надеяться не приходилось. Оставалось рассчитывать на привлекательность низкой цены. Было решено остановиться на стоимости $0.002 за минуту.

Читать далее
Total votes 1: ↑1 and ↓0+3
Comments4

Nota: Алгоритм выбора и ротации треков

Reading time3 min
Views2.5K


Это продолжение предыдущей статьи об умном радио, не умирающем при потере Интернета. Похоже, что первый блин был скорее комом: большинству пользователей приложение не понравилось. Критика в основном разделилась на два фронта:


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

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


Рад сообщить, что мне удалось решить первую проблему (обновление уже в Play Store). Под катом будет описание выбранного алгоритма выбора и ротации треков, а также сути исправления, которое, как я ожидаю, должно кардинально улучшить пользовательский опыт.

Читать дальше →
Total votes 13: ↑8 and ↓5+3
Comments16

Умное музыкальное радио, не требующее постоянного Интернет-соединения

Reading time3 min
Views7.9K

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


  • недоступность во время почти ежедневных прогулок по лесу (т.е. без подключения к Интернету).
  • Необходимость переключения между разными каналами, чтобы сменить жанр музыки. Другими словами, у слушателя Jango мало шансов открывать для себя новые музыкальные жанры.

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


Читать дальше →
Total votes 12: ↑10 and ↓2+8
Comments25

Библиотека для синхронизации состояния

Reading time4 min
Views6.2K



Так случилось, что на одном проекте потребовалось реформировать способ обмена данными между различными процессами. Исторически сложившаяся схема была довольно неприглядна. Один процесс периодически перезаписывал свои текущие настройки в виде XML-файла. Второй вычитывал этот файл раз в секунду, проверяя, что в нём поменялось с прошлого раза. Изменения файла вычислялись через множество сравнений текущего и прошлого его состояний, порождая некоторую цепочку действий. Читающий процесс писал в свою очередь другой XML-файл, который читался третьим процессом и т.п. Самое печальное то, что данная схема требовала громоздкого, из раза в раз повторяющегося кода сравнений, который наслаивался при добавлении новых данных.
Читать дальше →
Total votes 15: ↑13 and ↓2+11
Comments4

Система хранения для миллиардов записей с доступом по ключу

Reading time3 min
Views20K

Даже слон не выдержит столько данных


Постановка задачи


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


К такому количеству записей опробованные SQL/NoSQL системы хранения оказались плохо приспособлены, поэтому клиент предложил с нуля разработать специализированное решение.

Читать дальше →
Total votes 43: ↑30 and ↓13+17
Comments66

Мониторинг динамических XML-документов

Reading time4 min
Views7.1K

На работе в рамках проектирования новой системы интеграции устройств для мониторинга аудио/видео потоков возникла задача отслеживания, накопления и последующего анализа изменений их состояния. Состояние выдаётся через зоопарк динамических XML-документов, используемых, в основном, для наполнения legacy web-UI.

Для упрощения интеграции мною была предложена идея создания обобщённой библиотеки для сохранения структурированных diff-ов для (почти) произвольного XML. Поскольку эти diff-ы будут сохраняться с учётом структуры документа, это дало бы возможность очень экономно аккумулировать изменения состояния устройств, а также в будущем генерировать отчёты с аналитикой, диаграммами, и т.п. После недели запойного программирования я набросал работающий proof-of-concept, которым и хочу поделиться в данной статье.
Читать дальше →
Total votes 7: ↑7 and ↓0+7
Comments2

Разбор естественного языка: под капотом

Reading time4 min
Views15K


API синтаксического анализатора


Продолжаю свой предыдущий пост. Время сфокусироваться на деталях внутреннего устройства синтаксического анализатора. В качестве языка реализации я выбрал Go, поскольку хотел малой ценой получить параллельный (в смысле, использующий все доступные ядра CPU) производительный инструмент, без погружения в низкоуровневую пучину C++.

Полученный код предоставляет следующий API:
type Attribute struct {
    Name   string
    Value  string
}

type ParseMatch struct {
    Text            string
    Nonterminal     string
    Rule            string
    Attributes      []Attribute
    Submatches      []ParseMatch
    Hypotheses      []string
    HypothesisCount uint
}

func Parse(text, nonterminal string, hypotheses_limit uint) []ParseMatch

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

Итак, функция Parse берёт text — текст для разбора, nonterminal — название нетерминала (например, «sentence»), а также максимальное число выдвигаемых гипотез hypotheses_limit (об этом чуть ниже). Параметр nonterminal может быть пустым. В этом случае тексту будет сопоставляться лексический терминал, найденный в морфологической базе.

В терминах данного анализатора гипотеза — это предположение того, что нарушенное ограничение значения атрибута вызвано случайной причиной. Если анализатор встречает несоответствие значения атрибута ограничению, заданному рассматриваемым в данный момент правилом, а число выдвинутых гипотез не достигло hypotheses_limit, то данное несоответствие игнорируется. В противном случае рассматриваемое правило отбрасывается. Данный механизм удобен для отладки правил, но должен избегаться в реальной работе, поскольку чудовищно замедляет процесс разбора.
Читать дальше →
Total votes 15: ↑15 and ↓0+15
Comments14

Разбор естественного языка: грамматическая нотация

Reading time6 min
Views16K


Я уже довольно давно интересуюсь ИИ, особенно областью, связанной с пониманием машиной текстов, написанных на естественном языке. Как известно, классическая теория анализа текста разделяет этот процесс на три этапа:

  • Морфологический — анализ словоформ и их характеристик (число, падеж, и т.д.);
  • Синтаксический — выделение структуры предложения (отношения между словами);
  • Семантический — выделение смысла исходя из «модели мира»;

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

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

Из-за отсутствия у меня глубоких знаний в области нейронных сетей я решил следовать более проторенной тропой, а именно разработать BNF-подобную грамматическую нотацию и реализовать анализатор, использующий грамматические правила, описанные с её помощью. С этой точки зрения при разработке практически полезного анализатора основная работа заключается именно в построении достаточной системы правил (что у меня далеко до завершения). В следующем посте я опишу устройство реализованного анализатора, а пока хочу сфокусироваться на разработанной грамматической нотации.
Читать дальше →
Total votes 21: ↑20 and ↓1+19
Comments13

Пишу игрушечную ОС (о реализации sleep)

Reading time4 min
Views17K

Очередной пост для блога, посвященного работе над игрушечной ОС. В прошлый раз я писал про необходимость в простеньком драйвере AHCI (SATA). Прежде чем начать двигаться в этом направлении, я решил набросать инфраструктуру драйверов: общий интерфейс драйвера + уточнённый интерфейс драйвера устройства хранения. Формулирование этих интерфейсов выявило проблему, на которую я ранее не обращал внимания — проблему портируемости.

Не зависящий от платформы код (например, большая часть планировщика, вспомогательный код типа kprintf, ...) у меня перемешивается с кодом, заточенным только под x86_64 (системные таблицы дескрипторов, APIC, прерывания, ...). Хотя ничего не мешало мне сформулировать интерфейс драйвера, жёстко привязанного к x86_64 (в частности, свободно оперировать PCI-адресами), мне стало ясно, что без чёткого отделения кода, специфичного для конкретной платформы, от общего портируемого кода я буду лишь усугублять ситуацию. Итак, я принял решение перебрать всё написанное, отделив общий код (в корне src/) от кода, специфичного для платформы (в src/x86_64/). Этим я и занимался последние две недели.
Читать дальше →
Total votes 62: ↑57 and ↓5+52
Comments15

Пишу игрушечную ОС (о реализации мьютекса)

Reading time4 min
Views27K

Продолжаю блог о разработке игрушечной ОС (предыдущие посты: раз, два, три). Сделав паузу в кодировании (майские праздники, всё-таки), продолжаю работу. Только что набросал сканирование PCI-шины. Эта штука понадобится для работы с SATA-контроллером: следующее, что хочу сделать — это простенький драйвер диска. Он позволит поэкспериментировать с проецированием постоянной памяти на адресное пространство (своппинг, доведённый до логического конца). А пока хотел бы описать реализацию мьютекса.
Читать дальше →
Total votes 70: ↑63 and ↓7+56
Comments11

Пишу игрушечную ОС (доступнее о планировщике)

Reading time4 min
Views17K

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

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

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

Далее задачи будем называть потоками. Изначально задачи были однопоточными, и поток выполнения всегда соответствовал задаче. В настоящее время это уже не так, поэтому задача логически разделилась на два родственных понятия: процесс, как контейнер ресурсов, и поток, как независимая последовательность исполнения кода.
Читать дальше →
Total votes 51: ↑50 and ↓1+49
Comments29

Пишу игрушечную ОС (о планировщике)

Reading time4 min
Views22K

Продолжаю вести блог о разработке игрушечной ОС.

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

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

Кроме того, было бы здорово, если бы планировщик не занимался выделением памяти, а мог принимать и возвращать память, выделенную под поток кем-то другим. С одной стороны, это бы обеспечило гибкость произвольного резервирования памяти потоков. С другой – дало бы уникальную возможность сохранять поток во внешней памяти (например, на жёстком диске) с последующей его загрузкой и запуском с прерванного места.
Читать дальше →
Total votes 61: ↑55 and ↓6+49
Comments16

Пишу игрушечную ОС (о прерываниях)

Reading time4 min
Views50K

Данная статья написана в форме поста для блога. Если она окажется вам интересной, то будет продолжение.

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

Общая задумка (пока весьма далёкая от реализации) следующая: единое 64-битное адресное пространство с вечно живущими нитями (как у Phantom OS); виртуальная машина, обеспечивающая безопасность исполнения кода. На данный момент реализованы:

1. загрузка ядра при помощи multiboot-загрузчика (GRUB);
2. текстовый VGA-режим (16-цветов, kprintf);
3. простой интерфейс настройки отображения страниц;
4. возможность обработки прерываний на C;
5. идентификация топологии процессоров (сокеты, ядра, потоки) и их запуск;
6. работающий прототип вытесняющего SMP-планировщика с поддержкой приоритетов;

Пропустим описание multiboot-загрузки и работы с VGA-режимом (об этом не писал, разве что, ленивый). Про отображение страниц тоже не хочу писать, боюсь это будет скучно (может, в другой раз). Давайте лучше поговорим об обработке прерываний.
Читать дальше →
Total votes 116: ↑111 and ↓5+106
Comments17

LISP-интерпретатор на чистом C

Reading time21 min
Views20K
Я люблю язык C за его простоту и эффективность. Тем не менее, его нельзя назвать гибким и расширяемым. Есть другой простой язык, обладающий беспрецедентной гибкостью и расширяемостью, но проигрывающий C в эффективности использования ресурсов. Я имею в виду LISP. Оба языка использовались для системного программирования и имеют давнюю и славную историю.

Уже достаточно долго я размышляю над идеей, объединяющей подходы обоих этих языков. Её суть заключается в реализации языка программирования на основе LISP, решающего те же задачи, что и C: обеспечение высокой степени контроля над оборудованием (включая низкоуровневый доступ к памяти). На практике это будет система LISP-макросов, генерирующая бинарный код. Возможности LISP для препроцессирования исходного кода, как мне кажется, обеспечат небывалую гибкость, в сравнении с препроцессором C или шаблонами C++, при сохранении исходной простоты языка. Это даст возможность на базе такого DSL надстраивать новые расширения, повышающие скорость и удобство разработки. В частности, на этом языке может реализовываться и сама LISP-система.

Написание компилятора требуют наличие кодогенератора, а в конечном итоге — ассемблера. Поэтому практические изыскания стоит начинать с реализации ассемблера (для подмножества инструкций целевого процессора). Мне было интересно минимизировать какие-либо зависимости от конкретных технологий, языков программирования и операционной системы. Поэтому я решил с нуля реализовать на C простейший интерпретатор импровизированного LISP-диалекта, а также написать к нему систему макрорасширений, позволяющих удобно кодировать на подмножестве ассемблера x86. Венцом моих усилий должен стать результирующий загрузочный образ, выводящий «Hello world!» в реальном режиме процессора.

На текущий момент мною реализован работающий интерпретатор (файл int.c, около 900 строк C-кода), а также набор базовых функций и макросов (файл lib.l, около 100 строк LISP-кода). Кому интересны принципы выполнения LISP-кода, а также подробности реализации интерпретатора, прошу под кат.
Читать дальше →
Total votes 48: ↑44 and ↓4+40
Comments25

Ещё одна архитектура виртуальной машины (часть вторая)

Reading time4 min
Views1.4K
Данный пост является продолжением Ещё одной архитектуры виртуальной машины (части первой).

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


Читать дальше →
Total votes 20: ↑17 and ↓3+14
Comments7

Ещё одна архитектура виртуальной машины (часть первая)

Reading time5 min
Views4.3K
Данный пост является продолжением Ещё одной архитектуры операционной системы.

Определившись с базовыми идеями, я начал размышлять о том, с чего начать разработку, да, притом, так, чтобы, столкнувшись с трудностями, не потерять интерес. Справедливости ради, замечу, что эта попытка у меня далеко не первая. Например, в прошлый раз я по простоте душевной начал с написания загрузчика. Вдоволь наигравшись с реальным и защищённым режимами, я закончил на работающем прототипе, незаметно растеряв весь свой интерес. Текущая попытка началась с осознанного понимания того, что начинать стоит с API, причем для этого совсем не нужно вступать в интимные отношения с сегментными дескрипторами.

Нативный API (С/С++) не подходил по нескольким причинам. Во-первых, он требует разделённые адресные пространства, что влечёт за собой приличные накладные расходы на IPC и взаимодействие с ядром. Вдохновлённый современными веяниями, я хотел ОС одного адресного пространства. Во-вторых, нативный API не обеспечит бинарной совместимости кода между разными архитектурами. И, наконец, такой API будет препятствовать прозрачности удалённых вызовов. Итак, требовалась виртуальная машина. С неё я и решил начать.


Читать дальше →
Total votes 26: ↑22 and ↓4+18
Comments59

Ещё одна архитектура операционной системы

Reading time3 min
Views3.5K
Решил взять небольшую паузу в ежедневном хобби-кодировании, и поделиться с вами описанием того, что я, собственно, делаю. Итак, я пытаюсь разработать и реализовать виртуальную машину для несуществующей операционной системы, которую я, быть может, тоже когда-нибудь начну воплощать в жизнь. Не буду спорить с пеною у рта, доказывая, зачем нужна ещё одна ОС, отвечу кратко: главным образом затем, что мне это интересно.


Читать дальше →
Total votes 38: ↑32 and ↓6+26
Comments33

Разработка web-приложений на языке Common Lisp (часть третья)

Reading time6 min
Views4.1K
Данный обзор является небольшим путеводителем для тех, решился (или решается) доверить этому чудесному языку будущее своего стартапа. Несмотря на то, что основной акцент будет ставиться на web-разработке, я постараюсь осветить также и более общие темы, так или иначе связанные с Common Lisp. Материал почерпнут из собственного опыта разработки web-сервиса AlterMoby.

Третья часть этого обзора будет посвящена web-серверу Hunchentoot. Рассмотрим его архитектуру и базовые возможности. Кроме того, затронем некоторые смежные вопросы, в частности, генерацию HTML/XML.

image
Читать дальше →
Total votes 34: ↑32 and ↓2+30
Comments59

Разработка web-приложений на языке Common Lisp (часть вторая)

Reading time5 min
Views4.1K
Данный обзор является небольшим путеводителем для тех, решился (или решается) доверить этому чудесному языку будущее своего стартапа. Несмотря на то, что основной акцент будет ставиться на web-разработке, я постараюсь осветить также и более общие темы, так или иначе связанные с Common Lisp. Материал почерпнут из собственного опыта разработки web-сервиса AlterMoby.

Вторая часть этого обзора будет посвящена базовому конфигурированию Lisp-среды. Будет описана установка простой Lisp-системы. Кроме того, вкратце рассмотрим систему управления зависимостями ASDF.
image
Читать дальше →
Total votes 42: ↑38 and ↓4+34
Comments29

Разработка web-приложений на языке Common Lisp (часть первая)

Reading time4 min
Views8.9K
Данный обзор является небольшим путеводителем для тех, решился (или решается) доверить этому чудесному языку будущее своего стартапа. Несмотря на то, что основной акцент будет ставиться на web-разработке, я постараюсь осветить также и более общие темы, так или иначе связанные с Common Lisp. Материал почерпнут из собственного опыта разработки web-сервиса AlterMoby.

Первая часть этого обзора будет вводной. Опытные лисперы смогут смело его пропускать. В этой части я попробую объяснить, когда стоит использовать Lisp, и какая его реализация лучше подойдёт для построения web-приложений. Последнее, конечно, отразит лишь мою субъективную точку зрения.

image
Читать дальше →
Total votes 96: ↑84 and ↓12+72
Comments241

Information

Rating
6,273-rd
Location
Винница, Винницкая обл., Украина
Date of birth
Registered
Activity