Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Первые вещи сначала - не оптимизируют слишком рано. Весьма распространено провести время, тщательно оптимизируя блок кода только, чтобы найти, что это не было узкое место, что Вы думали, что это было. Или, выражаясь иначе, "Перед созданием его быстро сделайте, это работать"
Занимается расследованиями, существует ли какая-либо опция для оптимизации алгоритма прежде, чем оптимизировать код. Будет легче найти улучшение производительности путем оптимизации плохого алгоритма, чем это должно оптимизировать код, только затем для выбрасывания его при изменении алгоритма так или иначе.
И разрабатывают, почему необходимо оптимизировать во-первых. Чего Вы пытаетесь достигнуть? При попытке, скажем, улучшиться, время отклика к некоторому событию удаются, существует ли возможность изменить порядок выполнения минимизировать строго ограниченные во времени области. Например, при попытке улучшить ответ на некоторое внешнее прерывание можно ли сделать какую-либо подготовку в потерю времени между событиями?
, Как только Вы решили, что необходимо оптимизировать код, какой бит Вы оптимизируете? Используйте профилировщика. Сосредоточьте свое внимание (сначала) на областях, которые чаще всего используются.
Поэтому, что можно сделать о тех областях?
большинство упомянутых выше опций может использоваться в качестве части нормальной практики без любых вредных воздействий. Однако, если Вы действительно пытаетесь восполнить лучшую производительность: - занимаются расследованиями, где можно (безопасно) отключить проверку ошибок. Это не рекомендуется, но это сохранит Вас некоторое пространство и циклы. - Ручные части ремесла Вашего кода в ассемблере. Это, конечно, означает, что Ваш код больше не является портативным, но где это не проблема, можно найти сбережения здесь. Знайте хотя это, там потенциально время потерянные движущиеся данные в и из регистров, которые Вы имеете в Вашем распоряжении (т.е. удовлетворить использование регистра Вашего компилятора). Также знайте, что Ваш компилятор должен делать довольно хорошее задание самостоятельно. (конечно, существуют исключения)
Я рекомендовал бы оптимизировать использующие более эффективные алгоритмы и не сделал бы это машинально, но кодировал бы его тот путь от запуска. Позвольте компилятору разработать детали о мелочах, как он знает больше о целевом процессоре, чем Вы.
Для одного, я редко использую циклы для поиска вещей, я добавляю объекты к хеш-таблице и затем использую хеш-таблицу для поиска результаты.
, Например, у Вас есть строка к поиску и затем 50 возможным значениям. Таким образом вместо того, чтобы делать 50 strcmps, Вы добавляете все 50 строк к хеш-таблице и даете каждому уникальное число (только необходимо сделать это однажды). Тогда Вы поиск целевая строка в хеш-таблице и имеет один большой переключатель со всеми 50 случаями (или имейте указатели функций).
При поиске вещей с едиными наборами входа (как правила css), я использую быстрый код, чтобы отслеживать единственные возможные солитоны и затем выполнить итерации мысли те для нахождения соответствия. Как только у меня есть соответствие, я сохраняю результаты в хеш-таблицу (как кэш) и затем использую результаты кэша, если я получаю тот же самый входной набор позже.
Мои основные инструменты для более быстрого кода:
хеш-таблица - для быстрых поисков и для кэширования результатов
qsort - это - единственный вид, который я использую
bsp - для поиска вещей на основе области (карта, представляющая и т.д.)
Иногда необходимо решить, является ли это большим количеством пространства или большей скоростью, которая Вы после, который приведет почти к противоположной оптимизации. Например, чтобы получить все возможное от Вас пространство, Вы пакет структуры, например, пакет #pragma (1) и использование битовые поля в структурах. Для большей скорости Вы упаковываете, чтобы выровняться с предпочтением процессоров и избежать битовых полей.
Другой прием выбирает правильные алгоритмы изменения размеров для роста массивов через перевыделение, или лучше все еще запись Вашего собственного диспетчера "кучи" на основе Вашего конкретного приложения. Не принимайте тот, который идет с компилятором, самое лучшее решение для каждого приложения.
, Кроме того, необходимо измерить уровень.
В большей части встроенной системы я работал не было никаких профильных инструментов, таким образом, хорошо сказать профилировщика использования, но не очень практичное.
Первое правило в оптимизации скорости - , находят Ваш критический путь .
Обычно Вы будете находить, что этот путь не является таким длинным и не настолько сложным. Трудно сказать универсальным способом, как оптимизировать это, это, зависят от того, что является Вами выполнение и что находится в Вашем питании сделать. Например, Вы хотите, обычно избегают memcpy на критическом пути, поэтому когда-либо необходимо ли использовать DMA или оптимизировать ли, но что, если у Вас hw нет DMA? проверьте, является ли memcpy реализация лучшей, если не переписывают его.
не используют динамическое выделение вообще во встроенном, но если Вы по некоторым причинам делаете не, делают это в критическом пути.
Организуют Ваши приоритеты потока правильно, что, правильно реальный вопрос, и это - ясно конкретная система.
Мы используем очень простые инструменты для анализа узких мест, простой макрос, которые хранят метку времени и индекс. Немногие (2-3) выполнения в 90% случаев найдут, где Вы проводите свое время.
И последний обзор кода очень важный. В большей части случая мы избегаем, чтобы проблема производительности во время кода рассмотрела очень эффективный путь:)
Подставляемые функции! Вдохновленный профильными вентиляторами здесь я представил мое приложение и нашел небольшую функцию, которая делает некоторый bitshifting на кадрах MP3. Это делает приблизительно 90% всех вызовов функции в моем applcation, таким образом, я заставил его встроить и вуаля - программа теперь использует половину процессорного времени, которое это сделало прежде.
Собирающиеся профили выполнения кода получают Вас 50% пути там. Другие 50% имеют дело с анализированием этих докладов.
Далее при использовании GCC или VisualC ++ можно использовать "ведомую оптимизацию профиля", где компилятор возьмет информацию от предыдущего выполнения и перенесет инструкции сделать ЦП более счастливым.
В эти дни самые важные вещи в optimzation:
не беспокоятся оптимизацией, которая включает копию-и-вставку Ваш код (как развертывание цикла), или циклы переупорядочения вручную. Компилятор обычно делает лучшее задание, чем Вы при выполнении этого, но большинство из них не достаточно умно для отмены его.
Трудный подвести итог...
Структуры данных:
Алгоритмы:
Низкий уровень:
самый важный из всех: Имейте размеры рано, Мера часто, и никогда не делает предположения, основывайте свои взгляды и оптимизацию на полученных данных профилировщиком (используйте PTU).
Другая подсказка, производительность является ключевой для успеха приложения и должна быть рассмотрена во время проектирования, и у Вас должны быть ясные поставленные задачи.
Это далеко от того, чтобы быть исчерпывающим, но должно обеспечить интересную основу.
Другая вещь, которая не была упомянута:
Если возможно, сравните 0, не произвольным числам, особенно в циклах, потому что сравнение с 0 часто реализуется с отдельными, более быстрыми ассемблерными командами.
, Например, если это возможно, пишут
for (i=n; i!=0; --i) { ... }
вместо
for (i=0; i!=n; ++i) { ... }
Поскольку для моих приложений обычно не нужно много процессорного времени дизайном, я фокусирую на размере свои двоичные файлы на диске и в памяти. Что я делаю главным образом высматривает статически измеренные массивы и заменяет их динамично выделенной памятью, где это стоит дополнительного усилия free'ing память позже. Для сокращения размера двоичного файла я ищу большие массивы, которые инициализируются во время компиляции и помещают initializiation во время выполнения.
char buf[1024] = { 0, };
/* becomes: */
char buf[1024];
memset(buf, 0, sizeof(buf));
Это удалит 1 024 нулевых байта из двоичных файлов.DATA раздел и вместо этого создаст буфер на стеке во времени выполнения и заливке это с нулями.
РЕДАКТИРОВАНИЕ: О, да, и мне нравится кэшировать вещи. Это не C конкретный, но в зависимости от того, что Вы кэшируете, это может дать Вам огромное повышение производительности.
пз: сообщите нам, когда Ваш список закончен, мне очень любопытно.;)
Преждевременная оптимизация является корнем всего зла!;)
Избегайте использования "кучи". Используйте obstacks или средство выделения пула для идентичных размерных объектов. Поместите мелочи с коротким временем жизни на стек. alloca все еще существует.
Для оптимизации низкого уровня:
наиболее распространенные методы, с которыми я встретился:
Что касается общих рекомендаций, большинством из них уже звучат:
Моя любимая техника должна использовать хорошего профилировщика. Без хорошего профиля, говоря Вам, где узкое место находится, никакие приемы и методы не собираются помочь Вам.
Поскольку все другие сказали: профиль, профиль профиля.
Что касается фактических методов, тот, что я не думаю, был упомянут все же:
Горячий & Холодное Разделение Данных : Пребывание в кэше ЦП невероятно важно. Один способ помочь сделать это путем разделения структур данных на часто получаемый доступ ("горячий") и редко получало доступ к ("холодным") разделам.
пример: Предположим, что у Вас есть структура для клиента, который выглядит примерно так:
struct Customer
{
int ID;
int AccountNumber;
char Name[128];
char Address[256];
};
Customer customers[1000];
Теперь, позволяет, предполагают, что Вы хотите получить доступ к идентификатору и AccountNumber много, но не так имени и адресу. То, что Вы сделали бы, должно разделить его на два:
struct CustomerAccount
{
int ID;
int AccountNumber;
CustomerData *pData;
};
struct CustomerData
{
char Name[128];
char Address[256];
};
CustomerAccount customers[1000];
Таким образом, когда Вы - цикличное выполнение через свой "потребительский" массив, каждая запись составляет только 12 байтов и таким образом, можно приспособить намного больше записей в кэше. Это может быть огромной победой, если можно применить ее к ситуациям как внутренний цикл механизма визуализации.
основы / общий:
некоторые вещи, которые на самом деле помогли:
Выбирают размер/память:
Выбирают скорость (быть осторожными):
Если у кого-то нет ответа на этот вопрос, возможно, он мало что знает.
Также может быть, что они знают много. Я много знаю (ИМХО :-), и если бы мне задали этот вопрос, я бы спросил вас: почему вы думаете, что это важно?
Проблема в том, что любые априорные представления о производительности, если они не основанные на конкретной ситуации, являются предположениями по определению.
Я думаю, что важно знать методы кодирования для повышения производительности, но я думаю, что еще важнее знать , чтобы не использовать их , пока не будет поставлен диагноз. раскрывает, что существует проблема и что это такое.
Теперь я собираюсь противоречить себе и сказать, что если вы сделаете это, вы узнаете, как распознавать подходы к проектированию, которые приводят к проблемам, чтобы вы могли их избежать, и новичок, это звучит как преждевременная оптимизация.
Отличные списки. Я просто добавлю один совет, которого я не видел в приведенных выше списках, который в некоторых случаях может дать огромную оптимизацию с минимальными затратами.
пропустите компоновщик
, если у вас есть приложение, разделенное на два файла, например main.c и lib.c, во многих случаях вы можете просто добавить \ # include "lib.c"
в свой main.c, что полностью обойдет компоновщик и позволит значительно более эффективно оптимизировать компилятор.
Иногда Google - лучший инструмент оптимизации алгоритмов. Когда у меня возникает сложная проблема, небольшой поиск показывает, что некоторые ребята с докторской степенью нашли соответствие между этой и известной проблемой и уже выполнили большую часть работы.