Софтуерно Инженерство
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
Java Fundamentals
RoYaL avatar RoYaL SoftUni Team Trainer 6883 Точки

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

0
DimoUrumov avatar DimoUrumov 2 Точки

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

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

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

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

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

0
RoYaL avatar RoYaL SoftUni Team Trainer 6883 Точки

Компилира. Но и 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