Android 에서 SparseArray 성능 최적화 사용 방법
9565 단어 AndroidSparseArray성능 최적화
SparseArray(희소 배열).그 는 Android 내부 특유 의 api 입 니 다.표준 jdk 는 이러한 종류 가 없습니다.Android 내부 에 서 는 HashMap
건물 주 는 친 측 에 따 르 면 SparseArray 가 데 이 터 를 저장 하 는 데 사용 하 는 메모리 공간 이 확실히 HashMap 보다 작 습 니 다.잠시 후에 테스트 데 이 터 를 내 보 내 분석 하고 있 습 니 다.우 리 는 우선 양자 의 구조 적 특성 을 살 펴 보 자.
HashMap 은 배열 과 링크 의 결합 체 로 링크 해시 라 고 불 린 다.
SparseArray 는 단순 배열 의 결합 입 니 다.희소 배열 이 라 고 불 리 며 데 이 터 를 저장 할 때 추가 비용 이 들 지 않 습 니 다.구 조 는 다음 과 같 습 니 다.
이것 이 바로 두 사람의 구조 입 니 다.우 리 는 두 사람 이 도대체 어떤 차이 가 있 는 지 볼 필요 가 있 습 니 다.
우선 삽입:
HashMap 의 정렬 삽입:
HashMap<Integer, String>map = new HashMap<Integer, String>();
long start_map = System.currentTimeMillis();
for(int i=0;i<MAX;i++){
map.put(i, String.valueOf(i));
}
long map_memory = Runtime.getRuntime().totalMemory();
long end_map = System.currentTimeMillis()-start_map;
System.out.println("<---Map --->"+end_map+"<---Map --->"+map_memory);
실행 후 결과:
<---Map --->914
<---Map --->28598272
SparseArray 의 정렬 삽입:
SparseArray<String>sparse = new SparseArray<String>();
long start_sparse = System.currentTimeMillis();
for(int i=0;i<MAX;i++){
sparse.put(i, String.valueOf(i));
}
long sparse_memory = Runtime.getRuntime().totalMemory();
long end_sparse = System.currentTimeMillis()-start_sparse;
System.out.println("<---Sparse --->"+end_sparse+"<---Sparse --->"+sparse_memory);
// :
<---Sparse --->611
<---Sparse --->23281664
100000 개의 데 이 터 량 의 정렬 이 삽입 되 었 을 때 SparseArray 의 효율 이 HashMap 보다 높 은 것 을 볼 수 있 습 니 다.또한 사용 하 는 메모리 도 HashMap 보다 작 습 니 다.여기 의 정렬 은 i 의 값 이 작은 것 에서 큰 것 으로 증가 하 는 것 을 나타 내 는 것 입 니 다.서열 은 i 의 값 에 달 려 있 습 니 다.for 순환 내부 에서 어떻게 실행 하 느 냐 가 아 닙 니 다.실행 후의 결 과 를 통 해 우 리 는 SparseArray 가 정상 적 인 삽입 을 할 때 효율 이 HashMap 보다 훨씬 빠 르 고 일부 메모리 도 절약 한 다 는 것 을 알 수 있다.인터넷 에 서 는 이들 의 효율 문제 에 대해 많은 사람들 이 SparseArray 가 HashMap 의 삽입 과 검색 보다 효율 이 빠르다 고 오해 하고,또 다른 사람들 은 Hash 검색 이 당연히 SparseArray 의 2 분 검색 보다 훨씬 빠르다 고 생각한다.
사실 저 는 Android 에서
HashMap 역순 삽입:
System.out.println("<------------- 100000 Map --------------->");
HashMap<Integer, String>map_2 = new HashMap<Integer, String>();
long start_map_2 = System.currentTimeMillis();
for(int i=MAX-1;i>=0;i--){
map_2.put(MAX-i-1, String.valueOf(MAX-i-1));
}
long map_memory_2 = Runtime.getRuntime().totalMemory();
long end_map_2 = System.currentTimeMillis()-start_map_2;
System.out.println("<---Map --->"+end_map_2+"<---Map --->"+map_memory_2);
// :
<------------- 100000 Map --------------->
<---Map --->836<---Map --->28598272
SparseArray 역순 삽입:
System.out.println("<------------- 100000 SparseArray --------------->");
SparseArray<String>sparse_2 = new SparseArray<String>();
long start_sparse_2 = System.currentTimeMillis();
for(int i=MAX-1;i>=0;i--){
sparse_2.put(i, String.valueOf(MAX-i-1));
}
long sparse_memory_2 = Runtime.getRuntime().totalMemory();
long end_sparse_2 = System.currentTimeMillis()-start_sparse_2;
System.out.println("<---Sparse --->"+end_sparse_2+"<---Sparse --->"+sparse_memory_2);
//
<------------- 100000 SparseArray --------------->
<---Sparse --->20222<---Sparse --->23281664
위의 운행 결 과 를 통 해 우 리 는 SparseArray 와 HashMap 이 어떻게 삽입 되 든 데이터 양 과 동시에 전 자 는 후자 보다 일부 메모 리 를 절약 해 야 하지만 효율 은?역순 으로 삽입 할 때 SparseArray 의 삽입 시간 과 HashMap 의 삽입 시간 은 수량 급 이 아 닌 것 을 볼 수 있 습 니 다.SparseArray 는 삽입 할 때마다 2 분 으로 같은 값 이 삽입 되 었 는 지 확인 해 야 하기 때문에 이러한 역순 의 상황 은 SparseArray 의 효율 이 가장 떨 어 질 때 입 니 다.SparseArray 의 삽입 소스 코드 를 간단하게 보 겠 습 니 다.
public void put(int key, E value) {
int i = ContainerHelpers.binarySearch(mKeys, mSize, key); // .
if (i >= 0) { // i , key , value ..
mValues[i] = value;
} else { // , .
i = ~i; // i .
//i mSize . mKey mValue . . . . .
if (i < mSize && mValues[i] == DELETED) {
mKeys[i] = key;
mValues[i] = value;
return;
}
// , mKey , gc() .
if (mGarbage && mSize >= mKeys.length) {
gc();
// Search again because indices may have changed.
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
// , key value .
if (mSize >= mKeys.length) {
int n = ArrayUtils.idealIntArraySize(mSize + 1);
// key value . mSize
int[] nkeys = new int[n];
Object[] nvalues = new Object[n];
// Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
// copy . mKey mValue . .
System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
// .. .. .
mKeys = nkeys;
mValues = nvalues;
}
// i mSize . mKey .
if (mSize - i != 0) {
// Log.e("SparseArray", "move " + (mSize - i));
System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
}
// .
mKeys[i] = key;
mValues[i] = value;
mSize++;
}
}
이것 이 바로 SparseArray 삽입 함수 의 소스 코드 입 니 다.매번 삽입 방식 은 2 점 으로 찾 아야 합 니 다.따라서 거꾸로 삽입 할 때 상황 이 매우 나 빠 집 니 다.효율 적 으로 HashMap 에서 데이터 구 조 를 배 운 사람들 에 게 절대적 으로 졌 다 는 것 을 잘 알 고 있 습 니 다.Map 은 삽입 할 때 충돌 인자 에 대해 해당 하 는 결정 을 내 립 니 다.충돌 을 잘 처리 하 는 방식 이 있 습 니 다.모든 값 을 옮 겨 다 닐 필요 가 없습니다.따라서 역순 이 든 정상 적 인 삽입 의 효율 은 처리 충돌 방식 에 달 려 있 기 때문에 삽입 할 때 희생 하 는 시간 은 대체적으로 같 습 니 다.삽입 을 통 해 우 리 는 양자 의 차 이 를 알 수 있다.
다시 한 번 찾 아 보 겠 습 니 다.
System.out.println("<------------- 100000 Map --------------->");
HashMap<Integer, String>map = new HashMap<Integer, String>();
for(int i=0;i<MAX;i++){
map.put(i, String.valueOf(i));
}
long start_time =System.currentTimeMillis();
for(int i=0;i<MAX;i+=100){
map.get(i);
}
long end_time =System.currentTimeMillis()-start_time;
System.out.println(end_time);
//
<!--------- :175------------>
SparseArray 찾기:
System.out.println("<------------- 100000 SparseArray --------------->");
SparseArray<String>sparse = new SparseArray<String>();
for(int i=0;i<10000;i++){
sparse.put(i, String.valueOf(i));
}
long start_time =System.currentTimeMillis();
for(int i=0;i<MAX;i+=10){
sparse.get(i);
}
long end_time =System.currentTimeMillis()-start_time;
System.out.println(end_time);
//
<!----------- :239---------------->
저도 간단하게 검색 의 효율 을 테스트 했 습 니 다.한 데이터 나 몇 개의 데 이 터 를 조 회 했 습 니 다.이들 의 차 이 는 매우 작 습 니 다.데 이 터 량 이 100000 개 일 때 100000 개 를 찾 는 효율 은 Map 이 빠 릅 니 다.데 이 터 량 이 10000 일 때 차이 가 더욱 적 습 니 다.하지만 Map 의 검색 효율 은 한 수 이 겼 습 니 다.사실 제 가 보기 에는
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.