воскресенье, 24 мая 2009 г.

Сравнительный анализ фреймворков для работы с онтологиями под .NET и Java

Ни для кого не секрет, что львиная доля проектов, связанных с Semantic Web, разрабатывается на Java. Фреймворки для работы с семантическими онтологиями не являются исключением: все основные проекты (Jena, OWL API, Sesame и т. д.) написаны именно на Java. Единственным серьезным представителем, использующим .NET, является фирма Intellidimension с продуктами RDF Gateway и Semantics.SDK.

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

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

Перед погружением в технические детали скажу пару слов о фреймворке от Intellidimension (как наименее известном продукте для Java-ориентированного сообщества). В отличие от остальных рассматриваемых в этой статье фреймворков, которые являются OpenSource-проектами, RDF Gateway и Semantics.SDK распространяются с закрытыми исходными кодами и стоят достаточно приличных денег. Так, один лишь RDF Gateway 3.0 Enterprise стоит 10000$ (хотя версия 2.0 стоила «всего» 2000$). К слову, использованные при тестировании ризонеры - Pellet и Owlim - тоже не бесплатны: Pellet распространяется по dual license, а Owlim предлагает бесплатно лишь версию, работающую в памяти; версия, работающая с хранилищем, стоит 700 евро за каждое используемое процессорное ядро.

Тестирование
Передо мной стояла задача подобрать фреймворк для реализации проекта под .NET, поэтому Java-проекты в чистом виде меня не интересовали (изначально я даже не планировал их тестирование). Необходимо было выбрать средство interop’а между Java и .NET. Мой выбор пал на ikvm.net, который позволяет конвертировать jar’ы в .NET dll. Получив .NET-версию Jena, OWL API и Sesame, я принялся за их тестирование. Однако тестирование было бы неполным, если бы не содержало результатов тестирования Java-фреймворков в их родной среде. Таким образом, в тестировании участвуют: Intellidimension Semantics.SDK 1.0, OWL API 2.2.0+Pellet 2.0rc5 (как под Java, так и под .NET), Jena 2.5.7+Pellet2.0rc5 (как под Java, так и под .NET) и отчасти Sesame 2.24+SwiftOwlim 3.0b9.

Из первоначального тестирования пришлось исключить Sesame ввиду отличающейся от Semantic SDK и Pellet политики логического вывода в Owlim (Owlim - основной ризонер, используемый в связке с Sesame). Так, Pellet и Semantic SDK нацелены на вывод во время запроса (query-time reasoning), хотя и включают средства заблаговременного вывода; Owlim же нацелен на полный логический вывод (full materialization). Об этом мы еще поговорим в разделе «Общая информация о ризонерах».

В качестве тестовой была выбрана онтология Thesaurus 09.02d института NCI. Правда, в чистом виде она содержит ряд противоречивостей (inconsistency). После общения со службой поддержки противоречивости были выявлены. Я использовал модифицированную версию 09.02d (которую Вы можете скачать с моего dropbox’а), хотя сейчас уже доступна версия 09.04d, в которой данных противоречивостей нет.

Для тестирования была смоделирована следующая ситуация:
1. Сначала онтология из файла загружалась в модель;
2. Затем к этой модели последовательно выполнялось 3 SparQL-запроса (тексты запросов можно скачать здесь).

Сначала рассмотрим результаты тестирования первого этапа:
Несмотря на то, что .NET/ikvm-фреймворки медленнее своих Java-собратьев в 2-3 раза, они оказались быстрее Intellidimension.

В плане работы с памятью .NET оставил более приятное впечатление. Сборщик мусора в Java требует указания максимального объема оперативной памяти, который может быть выделен под кучу (параметр Xmx); .NET же использует более логичную, на мой взгляд, политику: он потребляет столько памяти, сколько ему нужно (если только не задано ограничение). Ограничение через Xmx - очень старый "баг", который, к сожалению, до сих пор не пофикшен. В качестве решения предлагается просто задавать Xmx с запасом (если, конечно, объем оперативной памяти позволяет), однако в этом случае (тестирование велось с Xmx:12g) сборщик мусора особенно себя не утруждает (что мы и видим по результатам тестирования). Можно пойти другим путем - подбирать минимальное значение Xmx для конкретных входных данных (правда, рискуя напороться на OutOfMemoryException). Таким образом можно приблизить объем потребляемой JVM памяти к аналогичным показателям CLR (пусть и с некоторыми дополнительными потерями производительности на более частые сборки мусора).

Касательно ограничения на максимальный объем используемой памяти произошел довольно курьезный случай. После успешной загрузки онтологии Thesaurus при помощи конвертированного в .NET OWL API, я решил открыть эту онтологию в Protége (который базируется на той же версии OWL API) для ознакомления с ее структурой. Однако вместо дерева концептов и экземпляров я получил OutOfMemoryException (при том, что свободной памяти было предостаточно). И хотя увеличение значения атрибута Xmx разрешило проблему, такая несамостоятельность сборщика мусора в Java не радует. Курьезность ситуации заключается в том, что несмотря на то, что Java-приложение не запускается в родной среде (без танцев с JVM), после конвертации в .NET при помощи ikvm оно работает.

Теперь перейдем ко второму пункту тестирования - выполнению SPARQL-запросов. К сожалению, на этом этапе придется оставить за бортом лидера первого теста - OWL API. Дело в том, что интерфейс OWL API, который реализуют ризонеры, не содержит методов для выполнения SPARQL-запросов. Связано это с тем, что SPARQL создавался как язык запросов к RDF-графам (и с OWL он не очень дружит), а OWL API, как нетрудно догадаться по названию, ориентирован именно на OWL. Сейчас идет работа над стандартом SPARQL-DL и, возможно, его поддержка будет реализована в одной из следующих версий OWL API. На данный момент остается лишь использовать class expressions, которые позволяют писать запросы с использованием манчестерского синтаксиса. Class expressions - это, конечно, не SPARQL… но для большинства задач их достаточно.

Итак, результаты тестирования:
Сначала прокомментирую прочерки в графе Intellidimension. С момента запуска тестового приложения прошло 6 часов, процесс весил порядка 6Гб, а результата все не было. Ждать дольше у меня не хватило терпения. Вынужден засчитать Semantics.SDK техническое поражение. Справедливости ради стоит отметить, что с более мелкими онтологиями Semantics.SDK справляется: и вывод делает, и запросы обрабатывает… правда, сравнивая результаты с Jena+Pellet, могу с уверенностью заявить, что Semantics.SDK не всегда выдает полный результат.

Pellet же справился с выводом за вполне разумное время (запросы были не из легких) и, как и на первом этапе тестирования, .NET/ikvm-фреймворк выглядит предпочтительнее Intellidimension.

На этом этап тестирования закончен. Подводя итоги, можно сказать, что победителем стала система Jena+Pellet, а приз авторских симпатий достается OWL API+Pellet.

Общая информация о ризонерах
В целом, существует два подхода к реализации логического вывода: на базе правил (с использованием алгоритмов forward-chaining и/или backward-chaining) и на базе семантического табло (semantic tableau). На базе правил реализованы Semantics.SDK и Owlim, а на базе семантического табло - Pellet.

Насколько я могу судить, rule-based ризонеры выгодно использовать для языков с низкой выразительностью, а ризонеры на базе семантического табло - для языков с высокой выразительностью. Если Pellet (OWL-DL) и Owlim (OWL-Tiny) подтверждают это наблюдение (находясь по разные стороны баррикады), то Semantics.SDK (OWL-FULL) является исключением (и судя по тестам производительности, ничего хорошего в этом исключении нет).

Рассмотрим диаграмму c официального сайта Owlim:
Как видим, Owlim поддерживает лишь OWL Tiny. Именно эта особенность позволяет ему добиться очень высокой производительности.

Owlim - единственный (из рассмотренных) ризонер, который поддерживает многопоточный вывод. Тем самым Owlim реализует преимущество rule-based систем перед семантическим табло - возможность распараллеливания (алгоритмов распараллеливания процесса построения семантического табло пока нет). Разработчики Semantics.SDK утверждают, что их вывод тоже распараллеливается… но в trial-версии это не реализовано (на мой взгляд, не самое удачное ограничение для trial-версии). Просьба выделить мне краткосрочную лицензию для тестирования осталась без ответа, поэтому приходится верить разработчикам на слово.

В идеальном мире определенно должен был бы существовать ризонер, который бы при анализе онтологии определял уровень выразительности и применял для ее вывода соответствующие алгоритмы. На данный момент такого ризонера нет, да и вряд ли он когда-либо появится.

Заключение
В этой статье акцент сделан на производительности, однако при выборе семантического фреймворка для того или иного проекта акцент нужно, в первую очередь, делать на функционале (поддержка (нереляционного) хранилища, поддержка OWL2 и т. д.). Обсуждение этих вопросов выходит за рамки данной статьи (да и не настолько хорошо я знаком с каждым из фреймворков, чтобы делать такой анализ). В отношении функциональности я хотел было похвалить продукты от Intellidimension: связка RDFGateway и Semantics.SDK представляет собой очень мощный фреймворк, аналогов которому в мире Java нет… но выкрутасы их ризонера охладили мои чувства к этому фреймворку.

P. S. Огромное спасибо за ликбез, оказанный в ходе написания статьи, Клинову Павлу.
PP. S. Статья также опубликована на shcherbak.net и на Хабре. Контент там тот же, а комменты (равно как и сообщество) совершенно разные - советую пролистать.

5 комментариев:

Flashr комментирует...

Хорошо пишешь. Видать науку собрался двигать, ибо на практике когда возникает подобная необходимость в масштабном объединении информационных ресурсов, то дело заканчивается постановкой продукта, типа BizTalk, и приведение все черед адаптеры(mediator) к общей модели данных (aka единая OWL) =(.


ЗЫ: у тебя есть шансы быть забаненным на хабре за копирование собственныз мыслей.

Idsa комментирует...

>>Видать науку собрался двигать, ибо >>на практике когда возникает >>подобная необходимость в >>масштабном объединении >>информационных ресурсов, то дело >>заканчивается постановкой >>продукта, типа BizTalk, и >>приведение все черед >>адаптеры(mediator) к общей модели >>данных (aka единая OWL)
Не всегда и не везде: статья родилась как результат выбора фреймворка для реального проекта.

>>ЗЫ: у тебя есть шансы быть >>забаненным на хабре за >>копирование собственныз мыслей.
Я в этом отношении не одинок. Вряд ли всех станут банить ;)

Flashr комментирует...

Тогда мне хотелось бы услышать поподробнее про вашу задачу для реального проекта. Неужели у Вас все с нуля и не потребуется того, что изображено на этой картинке - http://pic.ipicture.ru/uploads/090519/K4GJxPWjN1.png

Idsa комментирует...

FlashR, откуда картинка, если не секрет? Хотел бы ознакомиться с этой статьей.

Нас пока устраивает работа с онтологией в памяти. Есть мнение, что с приходом облачных вычислений, будущее именно за таким подходом. Хотя если понадобится хранилище, - прикрутим. А вот с интеграцией нескольких семантических хранилищ (если я правильно понял картинку) действительно все не так просто.

FlashR комментирует...

Картинка из моего блога, где я иногда что-то пишу по поводу семантического веба, но не про онтологии. Вот ссылку на все записи из этой категории - http://ya.topbot.ru/category/feed/Semantic-Web.aspx