| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > что работает быстрее? |
| Автор: polosatij 26.11.2004, 16:38 | ||||
| и всё с ней связанное: народ! нужна информация по оптимизации например, кто скажет, что работает быстрее: Vector() или ArrayList() может есть что-то другое, побыстрее? например, на http://forum.vingrad.ru/index.php?showtopic=24799&st=90 нашёл очень полезную для меня инфо. Еще цитируя Domestic Cat:
может еще кто что подскажет на это тему Domestic Cat, я не совсем понял, что ты подразумеваешь под: 6. Используйте Buffered{}Stream не объяснишь? ещё на эту тему:
млин! у меня большая проблема с передачей Диалогу: new Frame(). У меня такое ощушение, что new Frame() ест очень много памяти! из за этого похоже.. если я быстро вызываю новый Диалог (скажим, 2 раза подряд), всё моё приложение зависает на вечность если я передаю в Диалог -> null, то получаю исключение: nullOwnerException. есть ли другие методы заранее БОЛЬШОЕ паси |
| Автор: redrick 26.11.2004, 17:06 |
| Buffered{}Stream = BufferedInputStream || BufferedOutputStream ну буффер у них там есть - что тут еще скажешь : ...an application can write bytes to the underlying output stream without necessarily causing a call to the underlying system for each byte written. |
| Автор: Domestic Cat 26.11.2004, 17:12 | ||||||||
ArrayList почти тo ж самоe что i Vector, только несинхронизованный. Следовательно, он быстрее.
Буффированный стрим пишет(читает) сначала в буфер, когдa буфер заполняется, sодержимое передается системе. это быстрее, чем передавать системе каждый байт. все этo в апи ест:
U диалогa должен быть владелец - другой диалог или фрейm. Передавaй ему ссылку на уже имеющийся фрейм / диалоg или пользуйся чем либо другим JOptionPane, JWindow |
| Автор: polosatij 26.11.2004, 17:22 | ||
я javax.swing.*; не могу использовать.. у меня нет имеюшегося Фрэйма -> Applett. А Аплет не может выступить "прородичем" |
| Автор: Domestic Cat 26.11.2004, 17:28 | ||
Значит, передавай всем диалогам ссылку нa один и тот же фрейм:
|
| Автор: Sleepy_PIP 26.11.2004, 19:49 | ||||||
я несколько не понял цитаты DomestikCat - по поводу арифметики. - я всегда считал и считаю что мат. сопроцессор, который теперь есть везде, в любом ядре любого процессора на ПС будет гораздо лучше меня вычислять умножения (нет, не степени 2-ки - хотя и там оптимизация есть!), деления, и тем паче синусы и пр. тригонометрию. На самом деле мат. сопр - если разбираться в его кишках - в основном через таблицы и действует, редко когда через алгоритмы. но даже если через алгоритмы - это все равно будет быстрее доступа до элемента массива на J ИМХО конечно. т.е. эту цитату можно воспринимать как - "JVM не использует мат сопроцессор"????? Не, правда - для меня это будет открытием. |
| Автор: Domestic Cat 26.11.2004, 19:57 | ||
Дело здесь в том, что если считаешь sin/cos в Java, тo обрашется она к нативным функциям. Просмотреть значние в "своем" массиве будет быстрее, тем более еслi не нужна большая точн ость. |
| Автор: Sleepy_PIP 26.11.2004, 20:16 | ||||||||||
эээ ... разве 4-5 тактов процессора быстрее доступа к элементу массива в J (нет, я правда не знаю - но сопр за 4-5 тактов любую операцию сделает). Добавлено @ 20:21
тоесть я хотел сказать - это реально проверяли? и доступ к массиву быстрее сопроцессора? если действительно так - может JVM просто сопроцессор не использует? Я правда не знаю и интересуюсь ... |
| Автор: Domestic Cat 26.11.2004, 20:22 | ||||
сaм ВЫЗОВ нативноgo метоda медленнее Добавлено @ 20:23
могем и бенчмарк забацать ... после перекурa =) |
| Автор: Sleepy_PIP 26.11.2004, 20:26 | ||||
нее, погоди. я опять не понял. Если байт-код синуса не транслируется JVM в непосредственную команду сопроцессора - то так и будет. Дело в том, что речь насколько я надеюсь не о найтивных методах - а о ASM командах сопроцессору. Если JVM действительно транслирует вызовы скажем тригонометрии в вызовы какой-либо библиотеки - то да, но если напрямую в команду сопроцессора - то сопроцессор должен быть быстрее всех ... Вообщем пошел проверять |
| Автор: Domestic Cat 26.11.2004, 20:50 | ||||||
Вот такоj тест:
Результаты 3x запусков:
|
| Автор: Sleepy_PIP 26.11.2004, 20:57 | ||||||||
ничего себе. тоесть Math.cos(0.54231f); не транслируется в прямые вызовы сопроцессора. Так понять это? как-же так ... обидно ужас ... сопр. есть, но не используется Добавлено @ 21:02 жаль что не прошли времена когда о математике надо было заботиться. и жаль что это теперь в J ... теперь надо быть осторожнее в 10 крат. Спасибо! |
| Автор: Domestic Cat 26.11.2004, 21:09 | ||
JVM - это "надстройка " над ОС, напрямую она ничего не вызывает. |
| Автор: Sleepy_PIP 26.11.2004, 21:15 | ||||
да. мои заблуждения глубоки. учимся далше. .... |
| Автор: polosatij 26.11.2004, 21:51 |
| ещё один линк на тему оптимизации: http://lib.juga.ru/article/articleview/164/1/68 Добавлено @ 21:59 вот, откопал то, что, наверно, не только мне одному интересно будет прочитать ( и не один раз ) Объекты 1. уменьшайте число временных объектов (в том числе внутри циклов); 2. по возможности используйте старые объекты, не создавайте новых; 3. контролируйте процесс создания объектов * пишите простые конструкторы; * используйте метод clone(); * используйте методы для создания объектов: * public MyObject getInstance() { return new MyObject();} String 1. используйте метод append() класса StringBuffer взамен конкантации строк; 2. используйте массив char[] array для создания строки, а не класс StringBuffer; 3. используйте запись String myString = "Hello!"; вместо String myString = new String("Hello!"); 4. метод equalsIgnoreCase() работает быстрее, чем equals(), если длины строк не равны. Поля классов и экземпляров классов 1. используйте ключевое слово final для создания неизменных объектов; 2. избегайте повторной инициализации полей экземпляра класса; 3. делайте методы static/private; 4. время, затраченное на вызов метода, оценивается примерно по следующей схеме: static < final < instance < interface метод < synchronized метод. Память 1. используйте WeakReference для хранения элементов в больших таблицах; 2. используйте SoftReference для кэширования элементов; 3. используйте SoftReference для повторного использования памяти; 4. для замера времени исполнения фрагмента кода вызывайте System.gc(); Методы 1. не используйте без причины приведение типов; 2. не пишите громоздких методов; 3. операторы "n+=4" быстрее, чем "n=n+4"; 4. оператор int++ быстрее, чем short++ or byte++; 5. избегайте деления переменных типа long; 6. используйте итерацию, а не рекурсию. Синхронизация 1. по возможности избегайте синхронизации; 2. синхронизируйте блок, а не метод; 3. не используйте синхронизацию в циклах; 4. создавайте/используйте мониторы (Monitors) и мютексы (Mutex) взамен обыкновенной синхронизации. Класс Doubles 1. Double.toString(double) метод – очень медленный; 2. не создавайте Double-объект из строки; Общие советы 1. выполнение System.currentTimeMillis может занимать около 0.5ms; 2. научитесь понимать байт-код. |
| Автор: Sleepy_PIP 27.11.2004, 13:48 |
| кстати я был не прав. в большинстве прямо компилирующихся языков под любой платформой sin(cos, tg, и так далее) будет превращаться в первую очередь в вызов библиотечной. ф., а та уже в свою очередь задействует сопроцессор. что явно больше времени доступа к массиву даже с предвычислением индекса. да. |
| Автор: Sleepy_PIP 27.11.2004, 19:04 | ||
| объясните пожалуста. почему деление путем вычитания быстрее натурального деления? вот код:
вот результат: del by minus 16 milliseconds del by del 62 milliseconds все-ж - от чего так происходит? само деление - уже не вызов метода - это оператор, который вполне может быть выполнен на сопроцессоре, как в прочем и приведение типа. Однако как сказад DomesticCat - так оно и получается, деление путем вычитания быстрее Спасибо! PS: что еще интересно - результат в ll для ll/=5000; всегда будет 0. ... |
| Автор: Domestic Cat 27.11.2004, 20:21 | ||||||||
Ну не настолько же быстрее Просто у тебя ошибка: после первого прохода цикла
ll становится равным 0. Тогда все оставшиеся 999999 раз этот цикл пропускается. Во втором с,лучае ноль получается из-за того, что ты делишь 45000 на 5000 1000000 раз. После девятого деления ll становится равным 1, а 1/5000 дает 0, т.к. оба числа целые и выполняется целочисленное деление (остаток = 1, результат = 0) . Я сделал так:
и получил:
то есть скорость приблизительно одинакова. |
| Автор: Sleepy_PIP 27.11.2004, 20:25 | ||
| Спасибо. ошибку я проглядел а вот дельфевый код
выполняется в более чем 10 раз быстрее для деления. Правда тут есть одна тонкость - результат деления засовывается в вещественную переменную ... |
| Автор: Domestic Cat 27.11.2004, 20:33 | ||||
Ну, Делфи я не знаю, так что сказать не могу ничего. Если изменить так в Java коде:
то замедление незначительное: 330 мс против 390 мс. |
| Автор: Sleepy_PIP 27.11.2004, 20:37 | ||
сделал аналог дельфевому коду, с исправлением ошибок
но результаты все равно я не понимаю: del by minus 47 milliseconds del by del 93 milliseconds правда тут может влиять ll=45000; в цикле. неужели из-а этого? нет, не из-а этого. закоментаринивание в цикле ll=45000; дает все равно: del by minus 47 milliseconds del by del 94 milliseconds учусь! и еще на долго ... |
| Автор: Domestic Cat 27.11.2004, 20:40 | ||
Ну деление-то остается делением, оно все-таки медленнее
а конвертация - медленная штука. |
| Автор: Sleepy_PIP 27.11.2004, 20:44 | ||||||
сории, я еще не освоил дизасм (или как там в яве?) - не мог-бы ты привести во что выражается в байткоде вычитание и деление? случаем не в вызовы методов? Сильно похоже что jvm действительно не использует сопроцессор вообще ... только догадки ... Добавлено @ 20:46
дело в том, что конвертацией так-же может заведовать сопроцессор ... но увы и ах, я так и не понимаю на чем теряется время .... |
| Автор: Domestic Cat 27.11.2004, 20:50 | ||||
конвертацией занимается JVM, опкод l2d (в данном случае)
опкоды lsub и ldiv (для лонгов). Все это ни о чем не говорит, т.к. JVM всегда вызывает методы ОС, она не работает с процессором напрямую. |
| Автор: Sleepy_PIP 27.11.2004, 20:55 | ||||||||||||||
ааа. вот тыт понятно. Спасибо! а жаль между прочим! JVM все одно на всех платформах своя - могли-б и сопр. задействовать на прямую ... Добавлено @ 20:59
хотя я не прав опять - хочется выжать все из конкретной системы - пиши на компилирующихся в системный код языках. и все проблеммы будут разрешены |
| Автор: Zandr 17.3.2005, 08:09 | ||
| Ребята, зачем деление вычитанием? Причем просто вот так в цикле! Вчера вечером вспомнил, что можно делить столбиком, и что битовые операции очень быстрые. В общем вот что получилось:
Кому не лень, сравните сскорости с делением методом вычитания в случаях, когда а) число делится на бОльшее (т.е. нуль в результате) б) очень большое число делится на единицу, например. в) что-нибудь на что-нибудь, когда ответ - первые единицы (1, 2, 3, ...) Вот случай (б) должен оказаться показательным |
| Автор: Zandr 17.3.2005, 10:28 |
| Ой, жалко - то как...... Тута ошибочка есть неразрешимая почти... может вылазить при |a| > 0x40000000. Эх. |
| Автор: NotGonnaGetUs 17.3.2005, 18:20 |
| прикольно, запустил тест "деление путём вычитания" c ключом -server (взят выше) del by minus 31 milliseconds del by del 0 milliseconds без него, что-то порядка del by minus 47 milliseconds del by del 78 milliseconds %) Оптимизации это великолепно. Хотя вполне возможно, это следствие оптимизации цикла, в режиме -server. Так и есть. Если заменить 5000, на рандомный делитель int by = r.nextInt(4000)+1000; то обычное деление выигрывает в обычном и сервер моде. Короче говоря то, что делить вычитанием быстрее - тоже заблуждение. В случае -server / выигрывает в 2 раза, -client / выигрывает на 15-20% (1782 vs 1468 ms). |