Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Dismiss Notice

[Решено] Multiple lines in tablist

Discussion in 'Разработка плагинов для новичков' started by CoolBoy, Jun 4, 2016.

Thread Status:
Not open for further replies.
  1. fall.us

    fall.us Активный участник Пользователь

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Код цикла и код StringJoiner выполняет одно и тоже, а значит - не костыль.

    Сказали. И если программер не умеет делать реализации простых структур данных - такие никому не нужны.
     
  2. Хостинг MineCraft
    <
  3. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    "Я лучше знаю, что ты сказал."
    Костыль. И посмотри код StringJoiner'а, там принцип другой, да и производительность выше.
    И если программер не знает Java SE API, такой тоже никому не нужен. От него можно ждать только костыльные реализации.
     
    Last edited: Jun 15, 2016
  4. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Костыль - это кривая, но работающая затычка в коде. В данном случае собственная реализация стрингджойнера - велосипед, но может человек не может в жабу 8, всякое говно бывает.
     
  5. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Было бы велосипедом, если бы использовал хотя бы StringBuilder, а так - костыль.
    Если элементов много будет, то сколько там объектов StringBuilder наплодится?
     
  6. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Ваш велосипед - говно, что по производительности, что по стилю кода.

    А теперь к теме тса, просто \n - символ переноса, для тех кто не знает, потому и логично что он переносит строки, правда не везде в майнкрафте есть его поддержка. Можно ещё посмотреть сколько максимум символов вмещает строка и добивать пробелами, но вот это уже изврат.
     
  7. fall.us

    fall.us Активный участник Пользователь

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Да, пожалуй StringJoiner быстрее.
     
  8. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    С
    Code:
     if (i == WORD_COUNT - 1)
    заорал.
    Но если что, твой примитив иногда действительно быстрее.
     
  9. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Примитив будет быстрее только в случае 1го элемента, потому что у стрингджойнера есть накладные расходы на инициализацию стрингбилдера. Случаи до 100 элементов надо бенчить с учётом прогрева jvm, но это уже тонкости. В общем случае лучше использовать StringBuilder при конкатенации большого либо неизвестного заранее количества символов (строк).
     
  10. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Оказывается, что нет. Он так же быстрее, если элементов больше 850 тысяч.
    Code:
    /**
    * Little edit for much perfomance.
    * @author fall.us
    */
    public class Main {
    
        final static int WORD_COUNT = 1000000;
    
        public static void main(String[] args) {
            Random rand = new Random(System.currentTimeMillis());
            String[] strings = new String[WORD_COUNT];
    
            for (int i = 0; i < WORD_COUNT; i++) {
                strings[i] = String.valueOf(rand.nextLong());
            }
        
            long clockStrings, clockSJoiner, clockStart = System.currentTimeMillis();
        
            StringBuilder words = new StringBuilder();
            for (int i = 0; i < WORD_COUNT; i++) {
                words.append(strings[i]).append("\n");
            }
    
            clockStrings = System.currentTimeMillis() - clockStart;
            clockStart = System.currentTimeMillis();
    
            StringJoiner sj = new StringJoiner("\n");
            for (int i = 0; i < WORD_COUNT; i++) {
                sj.add(strings[i]);
            }
    
            clockSJoiner = System.currentTimeMillis() - clockStart;
            words = new StringBuilder();
            words.append("Overall time: ").append((clockSJoiner + clockStrings)).append(" ms\n");
            words.append("Strings: ").append(clockStrings).append(" ms\n");
            words.append("StringJoiner: ").append(clockSJoiner).append(" ms");
            System.out.println(words.toString());
        }
    }
     
  11. Автор темы
    CoolBoy

    CoolBoy Активный участник Пользователь

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    В другое русло пошли, господа.
     
  12. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Скорее всего аллокация памяти для стрингбилдера вызвала аллокацию памяти из системы, запускай из консоли с достаточным количеством выделенной памяти, ибо у меня на любом количестве элементов которые ещё могут влезть в массив джойнер быстрее.
     
  13. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Вообще интересно выходит. 349 мб рамы отъедает.
    2016 06 15_14-41-08.png

    Интересная картина. Но всё равно StringJoiner для плагинов будет быстрее, ибо на сервере майнкрафта не найдётся столько объектов, чтобы замедлить его (кроме блоков - они замедляют всё что можно и нельзя).
    Да плевать.
     
  14. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Xms забыл чтобы вся память сразу выделилась.
     
  15. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Тогда уже в двух случаях из трёх StringJoiner быстрее примитивного решения.
    2016 06 15_14-53-01.png
     
    Last edited: Jun 15, 2016
  16. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    СтрингБилдер почти всегда будет быстрее, так как конкатенация объектов String через "+" вызывает новый объект StringBuilder'а.
     
    Last edited: Jun 15, 2016
  17. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Хотел уже написать чзх, но потом увидел у себя очепятку. Спасибки.
     
  18. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Вот нормальный тест:
    Code:
    package dk.xakeps.benchmarks.strings;
    
    import org.openjdk.jmh.annotations.*;
    import org.openjdk.jmh.runner.Runner;
    import org.openjdk.jmh.runner.RunnerException;
    import org.openjdk.jmh.runner.options.Options;
    import org.openjdk.jmh.runner.options.OptionsBuilder;
    
    @State(Scope.Thread)
    @SuppressWarnings({"all"})
    public class Main {
    
        private StringBuilder stringBuilder1;
        private StringBuilder stringBuilder2;
    
        private StringBuffer stringBuffer1;
        private StringBuffer stringBuffer2;
    
        private String string1;
        private String string2;
    
        /*
         * re-initializing the value after every iteration
         */
        @Setup(Level.Iteration)
        public void init() {
            stringBuilder1 = new StringBuilder("foo");
            stringBuilder2 = new StringBuilder("bar");
    
            stringBuffer1 = new StringBuffer("foo");
            stringBuffer2 = new StringBuffer("bar");
    
            string1 = "foo";
            string2 = "bar";
    
        }
    
        @State(Scope.Benchmark)
        public static class BenchmarkState {
            volatile long builderConcatCount = 1;
            volatile long bufferConcatCount = 1;
            volatile long stringPlusCount = 1;
            volatile long stringConcatCount = 1;
        }
    
        /*
         * want to measure the progress from call to call so using the
         * SingleShotTime mode
         */
        @Benchmark
        @Warmup(iterations = 5, batchSize = 1)
        @Measurement(iterations = 100, batchSize = 1000)
        @BenchmarkMode(Mode.SingleShotTime)
        public StringBuilder stringBuilder(BenchmarkState state) {
            StringBuilder stringBuilder = null;
            for (long j = 0; j < state.builderConcatCount; j++) {
                stringBuilder = stringBuilder1.append(stringBuilder2);
            }
            state.builderConcatCount++;
            // to avoid dead code optimization returning the value
            return stringBuilder;
        }
    
        @Benchmark
        @Warmup(iterations = 5, batchSize = 1)
        @Measurement(iterations = 100, batchSize = 1000)
        @BenchmarkMode(Mode.SingleShotTime)
        public StringBuffer stringBuffer(BenchmarkState state) {
            StringBuffer stringBuffer = null;
            for (long j = 0; j < state.bufferConcatCount; j++) {
                stringBuffer = stringBuffer1.append(stringBuffer2);
            }
            state.bufferConcatCount++;
            // to avoid dead code optimization returning the value
            return stringBuffer;
        }
    
        /*
         * want to measure the progress from call to call so using the
         * SingleShotTime mode
         */
        @Benchmark
        @Warmup(iterations = 5, batchSize = 1)
        @Measurement(iterations = 100, batchSize = 1000)
        @BenchmarkMode(Mode.SingleShotTime)
        public String stringPlus(BenchmarkState state) {
            String string = null;
            for (long j = 0; j < state.stringPlusCount; j++) {
                string = string1 + string2;
            }
            state.stringPlusCount++;
            // to avoid dead code optimization returning the value
            return string;
        }
    
        @Benchmark
        @Warmup(iterations = 5, batchSize = 1)
        @Measurement(iterations = 100, batchSize = 1000)
        @BenchmarkMode(Mode.SingleShotTime)
        public String stringConcat(BenchmarkState state) {
            String string = null;
            for (long j = 0; j < state.stringConcatCount; j++) {
                string = string1.concat(string2);
            }
            state.stringConcatCount++;
            // to avoid dead code optimization returning the value
            return string;
        }
    
    
        public static void main(String[] args) throws RunnerException {
            Options options = new OptionsBuilder()
                    .include(Main.class.getSimpleName())
                    .threads(1)
                    .forks(1)
                    .shouldFailOnError(true)
                    .shouldDoGC(true)
                    .jvmArgs("-server", "-Xmx6G", "-Xms6G", "-XX:+UseG1GC")
                    .build();
            new Runner(options).run();
        }
    }
    
    Результаты:
    Code:
    "-server", "-Xmx6G", "-Xms2G", "-XX:+UseConcMarkSweepGC"
    # Run complete. Total time: 00:06:50
    
    Benchmark           Mode  Cnt  Score   Error  Units
    Main.stringBuffer     ss  100  0,733 ± 0,142   s/op
    Main.stringBuilder    ss  100  0,508 ± 0,107   s/op
    Main.stringConcat     ss  100  1,160 ± 0,226   s/op
    Main.stringPlus       ss  100  0,602 ± 0,117   s/op
    
    "-server", "-Xmx6G", "-Xms6G", "-XX:+UseConcMarkSweepGC"
    # Run complete. Total time: 00:06:55
    
    Benchmark           Mode  Cnt  Score   Error  Units
    Main.stringBuffer     ss  100  0,679 ± 0,123   s/op
    Main.stringBuilder    ss  100  0,482 ± 0,094   s/op
    Main.stringConcat     ss  100  1,221 ± 0,243   s/op
    Main.stringPlus       ss  100  0,661 ± 0,132   s/op
    
    "-server", "-Xmx6G", "-Xms2G", "-XX:+UseG1GC"
    # Run complete. Total time: 00:07:58
    
    Benchmark           Mode  Cnt  Score   Error  Units
    Main.stringBuffer     ss  100  0,717 ± 0,125   s/op
    Main.stringBuilder    ss  100  0,489 ± 0,091   s/op
    Main.stringConcat     ss  100  1,388 ± 0,278   s/op
    Main.stringPlus       ss  100  0,750 ± 0,152   s/op
    
    "-server", "-Xmx6G", "-Xms6G", "-XX:+UseG1GC"
    # Run complete. Total time: 00:08:11
    
    Benchmark           Mode  Cnt  Score   Error  Units
    Main.stringBuffer     ss  100  0,752 ± 0,149   s/op
    Main.stringBuilder    ss  100  0,516 ± 0,091   s/op
    Main.stringConcat     ss  100  1,300 ± 0,261   s/op
    Main.stringPlus       ss  100  0,625 ± 0,118   s/op
    
    Вывод: скорость зависит от настроек GC, а не от Xms.
     
  19. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    2гб - максимальный размер строки, аллокации лишней системной памяти так и так не произойдёт, xms надо вообще уносить, тогда совсем небольшая разница будет на малых количествах итераций. И прогрев надо тогда отрубать.
    Кстати судя по результатам теста jvm в итоге плюс таки превратила в стрингбилдер, дампани выхлоп jit, да и байткод не помешал бы.
     
  20. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Ага, что-то не подумал об этом. Потом сделаю тесты заново.
     
  21. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    А не, сам тестовый код косячный, ты скадываешь две строки каждый раз, в итоге тест тестит только скорость операций, нам же надо складывать всё в одну большую строку чтобы увидеть влияние сайд эффектов.
     
Thread Status:
Not open for further replies.

Share This Page