Java precompiled regex pattern performance comparisson
Здравейте,
опитвам се да направя сравнение на производителността на нормален и прекомпилиран регулярен израз. Оказва се (поне според резултатите от теста), че прекомпилираният код е по-бавен?! Можете ли да кажете дали логиката ми е правилна?
Това е кода на класа:
А това е кода да теста:
В крайна сметка ми се изплюва следния резултат:
Created big string
Created test class
PatternBenchmarkTest.testPrecompiled: [measured 10 out of 15 rounds, threads: 1 (sequential)] round: 0.34 [+- 0.04], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 9, GC.time: 0.76, time.total: 8.93, time.warmup: 5.54, time.bench: 3.39
PatternBenchmarkTest.testNonPrecompiled: [measured 10 out of 15 rounds, threads: 1 (sequential)] round: 0.29 [+- 0.05], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 5, GC.time: 0.32, time.total: 4.52, time.warmup: 1.63, time.bench: 2.88
Значи Pattern.compile("\\s+") не компилира нищо?
Все пак още в конструктора извиквам да се компилира шаблона:
public StringSplitter() { this.spacesPattern = Pattern.compile(REGEX_STRING); }
Можеш ли да дадеш пример (в код) как се компилира шаблон?
Благодаря предварително!!!
Компилира. Но и string.split() компилира шаблон, защо не му отвориш кода?:
Виждаш ли последни return най-отдолу? Правиш абсолютно същото - компилира шаблон и извиква split() върху него.
Това, което се опитах да ти обясня е че правиш точно ЕДНА операция. Кеширането (в случая прекомпилирането) има смисъл, ако ще го преизползваш. И в двата случая се случва точно една компилация и едно разделяне.
Добре. :) Не бях погледнал кода. Но все пак ако използвам прекомпилиран шаблон за многократна операция, би трябвало да е по-бързо, защото в единия случай шаблона се компилира само веднъж, а в другия при всяко извикване на string.split(...);
Промених теста така:
При което получавам следния резултат:
Разликата е пренебрежимо малка или никаква. Това значи ли, че компилатора оптимизира байткода предварително и практически няма по-бърз начин да се използва regex?
Здрасти,
Тестовете, които си написал са "нечестни". Бавната операция - bottleneck-a - е в създаването и в разделянето на стринга с 10000000 символа.
Компилирането на патърна, който е най-тривиалния възможен - празно място, минава за някакви милисекунди и изобщо не може да се усети на фона на другите операции.
Сложи по-сложен патърн за компилация, смени сплитването да е е само 1, повтори циклите на 10000 и тогава ще има реален резултат от това, което се опитваш да тестваш.
Също е лоша практика да тестваш по този начин 2 различни api-та все едно са еднакви, в случая - Pattern.compile() и String.split(). Това, че в Java едното ползва другото по-никакъв начин не гарантира, че в друг език ще е същото.
Идеята ми всъщност е следната:
Искам да проверя дали код (първи вариант), който предварително се компилира веднъж и се използва многократно, е по-бърз от код (втори вариант), който на всеки цикъл трябва да се компилира наново.
Но явно Java кешира по някакъв начин компилирания код от втори вариант и оптимизира алгоритъма до такава степен, че дори (поне при мен) е по-бърз от прекомпилирания и използван многократно код от първи вариант.
Надявам се, че ме разбрахте. :)