Loading...
DimoUrumov avatar DimoUrumov 2 Точки

Java precompiled regex pattern performance comparisson

Здравейте,

опитвам се да направя сравнение на производителността на нормален и прекомпилиран регулярен израз. Оказва се (поне според резултатите от теста), че прекомпилираният код е по-бавен?! Можете ли да кажете дали логиката ми е правилна?

Това е кода на класа:

https://pastebin.com/t5QEsR11

А това е кода да теста:

https://pastebin.com/Bf3WeBjc

В крайна сметка ми се изплюва следния резултат:

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

0
Module: Java Advanced
RoYaL avatar RoYaL Trainer 6849 Точки

Двата теста правят едно и също по веднъж. Единственият начин да направиш Pattern е да го компилираш. Ако кажеш matches()/split() това вътре ще направи компилиране на шаблон. Едно разделяне или една проверка за съвпадение ще направи точно една компилация на шаблон. Толкова, колкото и ръчното създаване на шаблон чрез компилация. Може би това, което искаш е върху прекомпилирания шаблон да направиш разделянето многократно. После да повториш операцията многократно и без прекомпилиран шаблон.

0
DimoUrumov avatar DimoUrumov 2 Точки

Значи Pattern.compile("\\s+") не компилира нищо?

Все пак още в конструктора извиквам да се компилира шаблона:

public StringSplitter() { this.spacesPattern = Pattern.compile(REGEX_STRING); }

Можеш ли да дадеш пример (в код) как се компилира шаблон?

Благодаря предварително!!!

0
RoYaL avatar RoYaL Trainer 6849 Точки

Компилира. Но и string.split() компилира шаблон, защо не му отвориш кода?:

    public String[] split(String regex, int limit) {
        char ch = 0;
        if (((regex.value.length == 1 &&
             ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ...) {
            int off = 0;
            int next = 0;
            // .. some stuff here
            String[] result = new String[resultSize];
            return list.subList(0, resultSize).toArray(result);
        }
        return Pattern.compile(regex).split(this, limit);
    }

Виждаш ли последни return най-отдолу? Правиш абсолютно същото - компилира шаблон и извиква split() върху него.

Това, което се опитах да ти обясня е че правиш точно ЕДНА операция. Кеширането (в случая прекомпилирането) има смисъл, ако ще го преизползваш. И в двата случая се случва точно една компилация и едно разделяне.

0
DimoUrumov avatar DimoUrumov 2 Точки

Добре. :) Не бях погледнал кода. Но все пак ако използвам прекомпилиран шаблон за многократна операция, би трябвало да е по-бързо, защото в единия случай шаблона се компилира само веднъж, а в другия при всяко извикване на string.split(...);

Промених теста така:

        @Test
	public void testNonPrecompiled() {
		for (int i = 0; i < 10; i++)
			pt.nonPrecompiledTest(bigS);
	}

	@Test
	public void testPrecompiled() {
		for (int i = 0; i < 10; i++)
			pt.precompiledTest(bigS);
	}

При което получавам следния резултат:


Created big string
Created test class
PatternBenchmarkTest.testPrecompiled: [measured 10 out of 15 rounds, threads: 1 (sequential)]
 round: 5.15 [+- 0.16], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 51, GC.time: 3.33, time.total: 83.03, time.warmup: 31.51, time.bench: 51.52
PatternBenchmarkTest.testNonPrecompiled: [measured 10 out of 15 rounds, threads: 1 (sequential)]
 round: 5.13 [+- 0.07], round.block: 0.00 [+- 0.00], round.gc: 0.00 [+- 0.00], GC.calls: 46, GC.time: 3.10, time.total: 76.73, time.warmup: 25.48, time.bench: 51.25
 

Разликата е пренебрежимо малка или никаква. Това значи ли, че компилатора оптимизира байткода предварително и практически няма по-бърз начин да се използва regex?

0
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.