[정상] 안 드 로 이 드 성능 최적화 무시 되 는 최적화 점
이 글 은 블 로 거들 본인 의 이해 에 대해 안 드 로 이 드 개발 에서 최적화 할 수 있 는 부분 을 다 루 고 있다.
Array List 와 Vector
Array List 와 Vector 는 모두 내부 에서 배열 로 이 루어 진 List 입 니 다. 이들 두 가지 유일한 차 이 는 다 중 스 레 드 에 대한 지원 입 니 다. Array List 는 스 레 드 가 안전 하지 않 고 Vector 내부 에서 대부분의 방법 을 동기 화 했 습 니 다. 스 레 드 가 안전 하기 때문에 성능 면 에서 Array List 보다 못 할 것 입 니 다. (물론 생각 이 옳 을 것 입 니 다) 그러나 이것 은 어떤 측면 을 봐 야 합 니까?Array List 는 add, get, remove 등 작업 효율 이 Vector 보다 높 을 것 이 고 메모리 에 있어 서 Vector 는 Array List 보다 더 잘 표현 되 었 습 니 다. 이 는 Array List 의 확장 전략 으로 인 한 것 입 니 다. 나중에 분석 하 겠 습 니 다.
RandomAccess 인터페이스의 집합 을 실현 하기 위해 fori 를 사용 합 니 다.
먼저 List 집합 을 옮 겨 다 니 는 방식 에 대해 이야기 합 니 다. 세 가지 가 있 습 니 다. foreach, iterator, fori.개발 에 있어 서 일반적으로 옮 겨 다 녀 야 할 때 첫 번 째 선택 은 foreach 일 것 이다. 효율 이 높 기 때문에 이 관점 은 맞 지만 장 소 를 나 누 어 합 쳐 야 한다.다음은 내 가 이 세 가지 방식 으로 100 w 개의 데 이 터 를 옮 겨 다 니 는 Array List 집합 을 테스트 하 는 것 이다.
long start = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
data.get(i);
}
long end = System.currentTimeMillis();
Log.v("zxy","fori :"+(end-start));
start = System.currentTimeMillis();
for (Integer integer : data) {
}
end = System.currentTimeMillis();
Log.v("zxy","foreach :"+(end-start));
Iterator<Integer> iterator = data.iterator();
start = System.currentTimeMillis();
while (iterator.hasNext()){
iterator.next();
}
end = System.currentTimeMillis();
Log.v("zxy","iterator :"+(end-start));
11-19 09:11:44.276 1418-1418/? V/zxy: fori :30
11-19 09:11:44.380 1418-1418/? V/zxy: foreach :105
11-19 09:11:44.476 1418-1418/? V/zxy: iterator :95
일반적으로 우리 가 말 하 는 효율 이 높 은 foreach 는 옮 겨 다 니 면서 도 뜻 대로 되 지 않 는 다. fori 효율 이 가장 좋 은 것 은 Array List 와 Vector 집합 내부 가 배열 로 이 루어 지기 때문에 무 작위 방문 속도 가 빠르다. 무 작위 방문 이 가능 한 List 에 대해 JDK 는 RandomAccess 인 터 페 이 스 를 실현 하여 빠 른 무 작위 방문 을 지원 한 다 는 뜻 이다.1w 개의 데 이 터 를 옮 겨 다 니 는 링크 드 리스트 집합 시:
11-19 09:33:23.984 1737-1737/? V/zxy: fori :351
11-19 09:33:23.988 1737-1737/? V/zxy: foreach :2
11-19 09:33:23.992 1737-1737/? V/zxy: iterator :4
foreach 가 가장 잘 표현 되 었 기 때문에 배열 이나 RandomAccess 인터페이스 의 List 를 실 현 했 습 니 다. fori 를 사용 하 는 성능 이 가장 좋 고 링크 드 List 등 링크 로 이 루어 진 집합 횟수 에 foreach 나 iterator 를 사용 하 는 성능 이 가장 좋 습 니 다. foreach 의 실현 은 iterator 를 통 해 이 루어 진 것 이기 때 문 입 니 다.우 리 는 이 List 가 어떤 방식 으로 옮 겨 다 니 는 지 이렇게 판단 할 수 있다.
if (list instanceof RandomAccess)
{
for (int i = 0; i < list.size(); i++) {}
} else {
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
}
}
용량 을 예지 한 상태 에서 ArrayList 를 구성 할 때 초기 크기 를 지정 합 니 다.
Array List 내부 의 확장 전략 은 저 장 된 요소 의 수량 이 기 존의 시간 을 초과 하면 1.5 배의 용량 으로 확대 하 는 것 이다. 즉, 현재 Array List 의 용량 이 10000 이 라면 하나의 요 소 를 더 저장 해 야 할 때 10001 번 째 요 소 는 용량 이 부족 해서 한 번 확장 되 고 Array List 의 용량 은 15000 으로 변 한다.한편, 하나의 요소 가 더 나 오 면 5000 개의 요소 의 공간 이 많아 집 니 다. 이것 은 메모리 자원 을 너무 낭비 하고 확장 하면 전체 배열 이 메모리 복 제 를 할 수 있 습 니 다. 한편, Array List 집합 은 기본 크기 가 10 이기 때문에 Array List 의 용량 을 합 리 적 으로 설정 하면 집합 이 확대 되 는 것 을 피 할 수 있 습 니 다.Array List 내부 확장 및 배열:
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
한편, Vector 내부 확장 전략 은 수요 에 따라 확장 하고 매번 + 1:
if (capacityIncrement <= 0) {
if ((adding = elementData.length) == 0) {
adding = 1;
}
} else {
adding = capacityIncrement;
}
E[] newData = newElementArray(elementData.length + adding);
마찬가지 로 많은 Map 집합 에서 도 각자 의 용량 확대 전략 이 있 는데 예 를 들 어 HashMap 이 매번 용량 을 확대 할 때마다 새로운 용량 은 원시 적 인 용량 * 2 와 같다.문자열 연결 을 자주 사용 하 는 StringBuffer 와 StringBuilder 내부 에서 도 확장 정책 이 있 습 니 다. 기본 값 은 원본 의 1.5 배 입 니 다.
따라서 이러한 확장 이 필요 한 api 에서 데이터 의 크기 를 미리 알 면 미리 설정 하면 확장 으로 인 한 공간 낭 비 를 피 할 수 있 을 뿐만 아니 라 내부 에서 System. array copy () 를 호출 하여 대량의 데 이 터 를 복사 하 는 것 도 피 할 수 있다.
프로그램 이 색인 아래 표 시 를 통 해 List 에 무 작위 로 접근 하려 면 Array List 와 Vector 를 우선 고려 해 야 합 니 다. 어 쩔 수 없 이 LinkedList 를 사용 하지 마 십시오.
Array List 는 메모리 에 있어 서 Vector 보다 못 하지만 데이터 조작 에 대한 효율 이 높 습 니 다. 특히 Android 등 모 바 일 장치 에 서 는 공간 을 희생 하고 시간 을 바 꾸 는 방식 을 취 하 는 것 이 바람 직 합 니 다. 스 레 드 안전 에 있어 서 는 Vector 를 사용 합 니 다.
이 대상 의 구성원 을 사용 할 필요 가 없 는 방법 이 있다 면 이 방법 을 static 로 설정 합 니 다.
정적 호출 방법 은 대상 호출 방법 보다 15% ~ 20% 빠 릅 니 다. 방법 서명 에서 이 방법 호출 이 대상 의 상태 에 영향 을 주지 않 음 을 알 수 있 기 때 문 입 니 다.
final 키 워드 를 교묘 하 게 사용 하 다.
final 키 워드 는 일반적으로 상수 와 방법 을 정의 하 는 데 많이 사용 되 는데 대부분 사람들 이 final 에 대한 이 해 는 흔히 불변성 에 있 고 final 은 성능 최적화 에 도 큰 역할 을 한다.예 를 들 어 static int AGE = 10;10 이 뒤에 인 용 될 때 필드 를 찾 는 과정 이 있 습 니 다. int 유형, 즉 방법 구역 의 전체 상수 풀 을 찾 는 것 입 니 다. final 의 상수 에 대해 서 는 이 과정 을 생략 합 니 다. 예 를 들 어 static final int AGE = 10;AGE 에 사용 되 는 곳 에 서 는 직접 10 으로 대체 된다.
그러나 위의 이러한 최적화 기법 은 기본 유형 과 String 유형 에 만 효과 가 있 고 다른 인용 유형 에 대해 서 는 효과 가 없 지만 우 리 는 상수 에 static final 을 추가 하 는 것 이 좋 은 습관 입 니 다.
final 키워드 와 강력 한 역할 을 합 니 다. 바로 사용 이 빈번 하고 최종 상태 로 확 정 된 방법 에 final 을 정의 하 는 것 입 니 다. 그러면 어떤 좋 은 점 이 있 습 니까?
이것 을 말 하기 전에 자바 에서 방법의 실행 과정 을 말 해 보 세 요. 어떤 방법 을 호출 할 때 먼저 이 방법 은 스 택 에 들 어 갑 니 다. 실행 이 끝 난 후에 이 방법 은 스 택 에서 나 오고 자원 이 방출 됩 니 다. 이 과정 내 부 는 메모리 주소 의 이전 과정 입 니 다. 스 택 에 들 어 가 는 방법 을 실행 할 때 사실은 프로그램의 실행 주 소 를 이 방법 으로 저장 하 는 메모리 주소 로 옮 기 는 것 입 니 다.이 작업 을 하기 전에 원래 프로그램 에서 실 행 된 메모리 주소 저장 과정 도 있어 야 합 니 다. 방법 이 스 택 에서 실 행 된 후에 저 장 된 주소 에 따라 프로그램 을 계속 실행 해 야 합 니 다. 이 과정 은 바로 방법의 호출 과정 입 니 다.
따라서 방법의 호출 과정 은 실제 적 으로 공간 과 시간 이 필요 한데 같은 방법의 빈번 한 호출 에 대한 최 적 화 는 실제 적 으로 내 연 을 사용 하 는 방법 이다.
또한 내 연 함수 에 대해 말하자면 내 연 함 수 는 실제 적 으로 컴 파일 기간 에 최적화 되 었 다. 컴 파일 러 는 내 연 으로 표 시 된 함 수 를 호출 하 는 곳 에서 전체 함수 체 로 직접 교체 하면 함수 호출 에 소모 되 는 시간 자원 을 절약 할 수 있 고 바 꾸 는 것 은 목표 코드 의 양 이 증가 하 는 것 이다.그래서 내 연 이라는 최적화 전략 은 실제 적 으로 공간 으로 시간 을 바 꾸 는 전략 을 취 했 기 때문에 이동 단 에 있어 내 연 함 수 를 교묘 하 게 사용 하 는 것 이 매우 유익 하 다.
한 함수 가 내 연 함수 가 되면 final 로 정의 합 니 다. 그러면 프로그램 이 컴 파일 할 때 컴 파일 러 는 자동 으로 final 함 수 를 내 연 최적화 시 킵 니 다. 그러면 이 함 수 를 호출 할 때 이 함수 체 를 직접 펼 쳐 사용 합 니 다.
결론 적 으로 내 연 함수 가 많 을 수록 좋 은 것 이 아니 라 한편 으로 는 우리 프로그램의 운영 효율 에 있어 서 확실히 향상 되 었 다. 다른 한편, 내 연 함 수 를 너무 많이 사용 하면 교묘 하 게 서 툴 러 지고 특정한 방법의 방법 체 를 크게 만 들 수 있 으 며 어떤 방법 체 가 비교적 큰 방법 에 대해 내 연 전개 시간 은 방법 호출 시간 을 초과 할 수 있다.그래서 이 는 성능 을 제공 하지 않 을 뿐만 아니 라 있어 야 할 성능 을 떨 어 뜨 렸 다.
종합 적 으로 보면 우 리 는 사용 이 빈번 하고 종 태 로 확 정 된 방법, 방법 체 가 크 지 않 은 방법 에 대해 final 로 수식 하여 프로그램의 성능 을 제공 할 수 있다.
스스로 쓰 는 것 이 아니 라 시스템 에서 제공 하 는 코드 를 우선 고려 합 니 다.
시스템 에 우리 가 사용 할 수 있 도록 매우 편리 한 api 가 많이 내장 되 어 있 습 니 다. 예 를 들 어 System, Arrays, Collections, String 등 은 여러 가지 방법 api 가 내장 되 어 있 습 니 다. 이것 은 우리 가 직접 쓰 는 것 보다 훨씬 편리 합 니 다. 이것 을 제외 하고 안 드 로 이 드 에 있어 많은 api 는 바 텀 C / C + + 를 사용 하여 실현 되 었 습 니 다. 효율 적 으로 도 우리 자신 보다 빠 릅 니 다. 마찬가지 로 시스템 api 에 대해 서도.DVM 은 종종 내부 연결 방식 을 사용 하여 효율 을 높 인 다.
이상
이상 을 조심 하 는 것 은 이상 을 사용 하지 않 는 것 이 아니 라 프로그램 에서 이상 을 던 지 는 방식 으로 어떤 조작 을 수행 하 는 것 을 말한다. 예 를 들 어 어떤 사람 은 강 한 이상 을 던 지 는 방식 으로 어떤 조작 을 중단 하 는 등 이다.이상 을 던 질 때 fillInStackTrace () 를 실행 하기 때 문 입 니 다.방법, 이 방법 은 스 택 을 재 조정 하 는 것 으로 이상 한 곳 을 사용 하지 않 아 도 된다.
어서 오 세 요.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
거품 정렬 최적화 알고리즘 (자바)기본 적 이 고 질서 있 는 데이터 에 대해 최 적 화 된 거품 정렬 을 사용 하 는 것 이 가장 좋 은 선택 이다. 그 는 데이터 가 질서 가 있 는 것 을 발견 한 후에 정렬 을 끝 낼 것 이다. 코드 는 다음 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.