К основному контенту

OpenNTF Domino API (ODA). Тест производительности

Сто лет назад анонсированный тест производительности ODA.

Обзорно что такое ODA, как ее использовать, какие возможности и преимущества можно почерпнуть из презентации. Основное. на чем я бы хотел остановиться, это обращение с View (слайды 25, 26), а именно - не только удобства написания кода, но сравнение производительности разных подходов к обходу view.


Основная мысль, что org.openntf.domino.DocumentCollection поддерживает интерфейс java.util.Collection, а значит не нужно использовать временный объект документа для хранения ссылки на следующий документ, а можно просто пройтись по коллекции, используя конструкцию for (Document doc : col).
НО. Важное НО. Последнее не относится к объекту View, а значит, чтобы обойти все вью нужно либо использовать один из вариантов:
- старый вариант конструкции (без .recycle(), кончено)
- пройтись по ViewEntry (ViewEntryCollection так же поддерживает интерфейс Collection)
- либо воспользоваться методом getAllDocuments у объекта view и, уже потом, использовать возможности Collection.

Давайте сравним производительность обхода именно представлений (а не как в примере из презентации всех документов из базы).
Критерии:
- 3 варианта количества документов: небольшое (порядка 1000), среднее (порядка 10 000) и большое (порядка 100 000) количество документов в базе (представлении)
- 5 вариантов обходов view:
1. по документам (используя пакет lotus.domino)
2. по ViewEntry (используя пакет lotus.domino)
3, по документам (используя пакет org.openntf.domino)
4. по ViewEntry (используя пакет org.openntf.domino)
5. по all documents из view (используя пакет org.openntf.domino)

Код для обхода 1
lotus.domino.Database ibmDb;
lotus.domino.View ibmView;
lotus.domino.Document ibmDoc;

long count = 0;
try {
 lotus.domino.Document ibmTmpDoc;
 
 ibmDb = ExtLibUtil.getCurrentSession().getDatabase(server, filePath)
 ibmView = ibmDb.getView(viewName);
 ibmDoc = ibmView.getFirstDocument();
 while (ibmDoc != null) {
  ibmTmpDoc = ibmView.getNextDocument(ibmDoc);
  
  ibmDoc.getItemValueString("Form"); //Делаем что-то
  count++;
  
  ibmDoc.recycle();
  ibmDoc = ibmTmpDoc;
 }
 
 ibmView.recycle();
 ibmDb.recycle();
 System.gc();
} catch (Exception e) {
 e.printStackTrace(System.out);
}

Код для обхода 2
lotus.domino.Database ibmDb;
lotus.domino.View ibmView;
lotus.domino.Document ibmDoc;
lotus.domino.ViewEntryCollection ibmEntryCol;
lotus.domino.ViewEntry ibmEntry;

long count = 0;
try {
 lotus.domino.ViewEntry ibmTmpEntry;
 
 ibmDb = ExtLibUtil.getCurrentSession().getDatabase(server, filePath);
 ibmView = ibmDb.getView(viewName);
 ibmEntryCol = ibmView.getAllEntries();
 ibmEntry = ibmEntryCol.getFirstEntry();   
 ibmDoc = ibmView.getFirstDocument();
 while (ibmEntry != null) {
  ibmTmpEntry = ibmEntryCol.getNextEntry();
  
  ibmEntry.getColumnValues().get(0);
  count++;
  
  ibmEntry.recycle();    
  ibmEntry = ibmTmpEntry;
 }
 
 ibmEntryCol.recycle();
 ibmView.recycle();
 ibmDb.recycle();
 System.gc();
} catch (Exception e) {
 e.printStackTrace(System.out);
}

Код для обхода 3
org.openntf.domino.Database odaDb;
org.openntf.domino.View odaView;
org.openntf.domino.DocumentCollection odaCol;
org.openntf.domino.Document odaDoc;

long count = 0;

try {
 org.openntf.domino.Document tmpDoc;
 
 odaDb = Factory.getSession().getDatabase(server, filePath);
 odaView = odaDb.getView(viewName);
 odaDoc = odaView.getFirstDocument();
 while (odaDoc != null) {
  tmpDoc = odaView.getNextDocument(odaDoc);
  
  odaDoc.getItemValueString("Form");
  count++;
  
  odaDoc = tmpDoc;
 }   
} catch (Exception e) {
 e.printStackTrace(System.out);
}

Код для обхода 4
org.openntf.domino.Database odaDb;
org.openntf.domino.View odaView;
org.openntf.domino.DocumentCollection odaCol;
org.openntf.domino.Document odaDoc;

long count = 0;

try {
 
 odaDb = Factory.getSession().getDatabase(server, filePath);
 odaView = odaDb.getView(viewName);
 for (org.openntf.domino.ViewEntry entry : odaView.getAllEntries()) {
  entry.getColumnValues().get(0);
  count++;
 }
 
} catch (Exception e) {
 e.printStackTrace(System.out);
}

Код для обхода 5
org.openntf.domino.Database odaDb;
org.openntf.domino.View odaView;
org.openntf.domino.DocumentCollection odaCol;
org.openntf.domino.Document odaDoc;

long count = 0;

try {
 odaDb = Factory.getSession().getDatabase(server, filePath);
 odaView = odaDb.getView(viewName);
 odaCol = odaView.getAllDocuments();
 for (org.openntf.domino.Document doc : odaCol) {
  doc.getItemValueString("Form");
  count++;
 }
} catch (Exception e) {
 e.printStackTrace(System.out);
}

Анализ результатов:
* значение - чистое время цикла по документам. В ячейке, где 2 значения, 2ое - время на получение коллекции ViewEntry или AllDocuments в последнем случае:

Алгоритм\Количество документов

995

9 895

355 000
IBM. Documents (1) 983ms. 289 mics. 833 nsec4 s. 969ms. 724 mics. 694 nsec 11 m. 22 s. 717ms. 841 mics. 927 nsec
IBM. Entries (2) 418ms. 859 mics. 516 nsec

18ms. 31 mics. 48 nsec
6 s. 153ms. 863 mics. 167 nsec

478ms. 754 mics. 808 nsec
4 m. 17 s. 827ms. 189 mics. 872 nsec

1 m. 4 s. 154ms. 29 mics. 557 nsec
ODA. Documents (3) 703ms. 561 mics. 53 nsec 5 s. 275ms. 29 mics. 925 nsec 11 m. 43 s. 732ms. 460 mics. 699 nsec
ODA. Entries (4) 390ms. 481 mics. 569 nsec

50ms. 571 mics. 307 nsec
7 s. 342ms. 324 mics. 198 nsec

1 s. 38ms. 765 mics. 806 nsec
4 m. 41 s. 755ms. 341 mics. 120 nsec

17 s. 839ms. 227 mics. 295 nsec
ODA. All Documents (5) 78ms. 6 mics. 207 nsec

192ms. 979 mics. 160 nsec
2 s. 935ms. 343 mics. 393 nsec

3 s. 34ms. 877 mics. 910 nsec
2 m. 49 s. 593ms. 108 mics. 790 nsec

3 m. 58 s. 903ms. 914 mics. 108 nsec

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

Тесты показывают примерно одинаковую тенденцию и важно смотреть на порядок:
- при небольшом количестве документов хорошую производительность дает ODA с проходом по всем документам (view.getAllDocuments()).
- при среднем количестве документов алгоритмы 1, 3, 5 дают сравнительно одинаковые результаты
- при большом количестве документов не плохо справляются 2, 4, 5.
Получается, что в усредненном варианте алгоритм 5 получается наиболее предпочтительным.

Комментарии

Популярные сообщения из этого блога

Занимательные алгоритмы. Поиск цикла в односвязном списке

И снова про тараканов, которые иногда возникают в голове. Как-то раз, засыпая, я задумался на курьезными задачками из своей сферы деятельности (Lotus Notes), которые можно было бы задать на собеседовании, плавно перешел к воспоминаниям о своих первых собеседования, когда опыта работы еще не было. Опыт самих собеседований у меня не велик а места, где задавались действительно интересные задачи (а не задачки типа: написать сортировку массива любым известным способом) вообще равны одному - это ABBYY. Как минимум одна задачка в списке на знание и понимание классических алгоритмов, описанных в книге Дональда Кнута -  Искусство программирования .

Unit-testing object validation when validator has DI

Summary Unit test object validation when validator(s) has a dependency. For instance, we have some custom field and cross-field validators. Want to test their combination. Additionally some of validators have dependencies, injected through constructor or setters. You're not using property injection, right? Shortcut If you are just searching for an answer, here's the fast way: Declare CustomConstraintValidatorFactory that implements javax.validation.ConstraintValidatorFactory Override getInstance method and on facing your constraint validator class instantiate it Otherwise delegate validator construction to org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl Build validator factory and provide it your CustomConstraintValidatorFactory Build validator, using that factory... Go to demo project on GitHub for details:  https://github.com/MrArtemAA/blog-demos/blob/master/test-validator-with-injection/src/test/java/ru/artemaa/d

Lotus Notes FAQ. 8/9 Eclipse. Как настроить уведомления о Sametime сообщениях

Н а написание данной "инструкцию" натолкнул мой коллега. Помню, первый раз сам долго искал, как отключить постоянно выпрыгивающие уведомления о новых сообщениях в Sametime. И так, речь идет о клиентах IBM Notes 8+ версии Standart (Eclipse based). Как настроить уведомления о Sametime сообщениях?