'Technical Note'에 해당되는 글 134건

Technical Note/LINUX

0. 개요


서버 작업을 하다 보면, 여러대 서버에 접속 해서 같은 작업을 해야 하는 경우가 있다.


하나하나의 서버에 다 접속 해야 되고, 명령어도 다 써줘야 한다.


이런 작업이 자주 있을때, 효율 적으로 작업 할 수 있도록 간단한 스크립트를 만들어 보겠다.




1. 준비


SSH 자동 로그인 스크립트를 만드릭 위해서는 sshpass 라는 툴이 필요 하다.


우분투에서는 apt-get -y install sshpass 로 바로 설치가 가능 하고


centos, sulinux..등은 소스를 다운 받아 컴파일 해줘야 한다.




2. sshpass 툴 옵션


sshpass -p 패스워드 ssh 아이디@도메인 명령어


    예) sshpass -p 123456 ssh abcde@abcde.co.kr


이때, -p 옵션 다음에 나오는 패스워드를 위와 같이 사용하기 싫으면 vi로 파일을 만들어 거기에 적어 놓고 사용 할 수 있다


    예) vi pass


         123456




         sshpass -f pass ssh abcde@abcde.co.kr




이렇게 간단하게 로그인 되면 좋겠지만. 처음 접속 하는 서버나, 디스크 등의 문제로 교체 및 재설치 하는 경우


known host에 저장 할 것인가? 라는 메세지가 뜬다. 이럴때 아래와 같이 사용하면 된다.


     예) sshpass -f pass ssh -oStrictHostKeyChecking=no ssh abcde@abcde.co.kr


-oStrictHostKeyChecking=no 옵션은 known host에 저장 할 것이냐는 질문에 yes를 누르고 넘어가는 옵션이다.




3. SSH 자동 로그인 스크립트 예제


접속 해서 작업 해야 하는 서버가 1~2대 일경우는 이런 스크립트도 필요 없이 작업 하면 되지만.


10대 20대 30대 이렇게 점점 만아 질수록, 한숨 부터 나온다.


vi login.sh


#!/bin/bash


for i in $(seq 1 10); do

        sshpass -f pass ssh -oStrictHostKeyChecking=no root@192.168.0.${i} "ls; exit;"

done


위 예제는 IP 192.168.0.1에서 192.168.0.10번 서버까지 접속 해서 ls 명령을 내리는 스크립트 이다.


########################################################################################


vi hosts.allow.sh


#!/bin/bash


for i in $(seq 1 10); do

        sshpass -f password ssh -oStrictHostKeyChecking=no root@192.168.0.${i} "echo "ALL : 192.168.100.3" >> /etc/hosts.allowt; exit"

done


위 예제는 hosta.allow에 ALL : 192.168.100.3 을 추가하는 내용이다.




4. 마무리


위 스크립트는 간단 하지만, 많은 서버에 작업을 해야 할 경우 아주 유용하다.


간단한 예를 들어 설명을 했지만, 주기적으로 해야 되는 패스워드 변경 작업 등


조금만 더 생각 해보면 많은 곳에 사용 할 수 있는, 유용한 스크립트이다.

Technical Note/NoSQL

http://datamining.dongguk.ac.kr/wiki/index.php/Hadoop_%EB%AA%85%EB%A0%B9%EC%96%B4



###############################################################

본 문서는 hadoop 클러스터를 구축하는 방법에 대하여 설명한다.

###############################################################

* 테스트 환경은 아래와 같다.

* OS: ubuntu 12.04

* 클러스터 환경: 1대의 master와 5대의 slave


[목 차]

1. Java 설치 

2. SSH 설치 및 공개 키 설정

3. hadoop 설치


########################################################

# 1. Java 설치 

#    hadoop은 java로 구현되었기 때문에 java를 반드시 설치해야 한다.

########################################################


1.1 java 설치

----------------------------------------------------------------------------------

$ sudo add-apt-repository ppa:upubuntu-com/java

$ sudo apt-get update

$ sudo apt-get install oracle-java7-installer

----------------------------------------------------------------------------------

(주1) Ubuntu를 최소 시스템으로 설치하여 "add-apt-repository" 명령어를 찾을 수 없는 경우

      아래를 실행한 후 1.1 실행할 것

        $ sudo apt-get install python-software-properties


1.2 자바 설치 확인

----------------------------------------------------------------------------------

$ java -version

----------------------------------------------------------------------------------

########################################################

#java version "1.7.0_04"

#Java(TM) SE Runtime Environment (build 1.7.0_04-b20)

#Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)

########################################################




########################################################

# 2. SSH 설치 및 공개 키 설정 

#   :  hadoop클러스터에서 master와 slave들 간에 통신은 SSH를 이용한다. 

#      따라서 모든 컴퓨터들은 SSH를 설치 해야 하고, 

#      master에서 암호없이 slave에 접속하기 위해서 공개 키가 필요하다.

########################################################


2.1 SSH 설치

- ubuntu를 설치했을 경우는 기본적으로 ssh가 설치 되어있지만, 설치가 안되있다면 아래의 코드를 통해 설치

----------------------------------------------------------------------------------

$ sudo apt-get install ssh

----------------------------------------------------------------------------------



2.2 공개 키 설정

- 모든 slave에 master ip 등록

----------------------------------------------------------------------------------

$ sudo vi /etc/hosts.allow

----------------------------------------------------------------------------------

sshd: 203.247.248.250 # master ip 또는 ALL


- [master] 공개 키 생성

----------------------------------------------------------------------------------

$ sudo vi /etc/ssh/sshd_config

----------------------------------------------------------------------------------

PubkeyAuthentication yes

AuthorizedKeysFile      .ssh/authorized_keys


----------------------------------------------------------------------------------

$ mkdir ~/.ssh

$ ssh-keygen -t rsa -P ""

$ cp /home/stat/.ssh/id_rsa.pub /home/stat/.ssh/authorized_keys

----------------------------------------------------------------------------------


- [master] master에서 생성한 공개 키를 모든 slave로 복사

----------------------------------------------------------------------------------

          $ scp /home/stat/.ssh/authorized_keys 203.247.248.241:/home/stat/.ssh/.

          $ scp /home/stat/.ssh/authorized_keys 203.247.248.242:/home/stat/.ssh/.

          $ scp /home/stat/.ssh/authorized_keys 203.247.248.243:/home/stat/.ssh/.

          $ scp /home/stat/.ssh/authorized_keys 203.247.248.244:/home/stat/.ssh/.

          $ scp /home/stat/.ssh/authorized_keys 203.247.248.245:/home/stat/.ssh/.

          scp /home/stat/.ssh/authorized_keys 203.247.232.233:/home/jskim/.ssh/.

----------------------------------------------------------------------------------


- [master, slaves] 디렉토리 및 파일 권한 변경

----------------------------------------------------------------------------------

        $ chmod 755 ~/.ssh

        $ chmod 644 ~/.ssh/authorized_keys

----------------------------------------------------------------------------------


-test

----------------------------------------------------------------------------------

        $ sudo /etc/init.d/ssh restart

        $ ssh localhost

----------------------------------------------------------------------------------


- 행여 안될 경우에는 ssh-keygen -R 203.247.248.241 또는 known_hosts를 지우고 위의 공개 키 설정 절차를 다시 실행

(기존에 저장되있던 hosts(공개 키)때문에 안되는 경우가 발생함)


- host 지정 (master와 slave 모두 설정)

----------------------------------------------------------------------------------

        $ sudo vi /etc/hosts

----------------------------------------------------------------------------------

                203.247.248.250 master

                203.247.248.241 slave01

                203.247.248.242 slave02

                203.247.248.243 slave03

                203.247.248.244 slave04

                203.247.248.245 slave05


- hosts 일치

        ex) master의 경우

----------------------------------------------------------------------------------

        $ sudo vi /etc/hostname

----------------------------------------------------------------------------------

                master  


----------------------------------------------------------------------------------

        $ sudo /bin/hostname -F /etc/hostname

----------------------------------------------------------------------------------

                

        ex) slave01의 경우

----------------------------------------------------------------------------------

        $ sudo vi /etc/hostname

----------------------------------------------------------------------------------

                slave01 


----------------------------------------------------------------------------------

        $ sudo /bin/hostname -F /etc/hostname

----------------------------------------------------------------------------------




##############################################

############### 3. hadoop 설치 ###############

##############################################

- hadoop을 구축하기 위해서는 동일하게 설정된 hadoop관련 파일을 master와 slave에 설치해야 한다. 

 이에 master에 hadoop파일을 설정 한 후에 동일한 파일을 slave에 복사하는 절차로 hadoop 클러스터를 구축하도록 하겠다.


1) hadoop 다운로드 및 압축 해제

        $ cd /home/stat

        $ wget http://mirror.apache-kr.org//hadoop/common/hadoop-1.0.3/hadoop-1.0.3.tar.gz

        $ tar xvfz hadoop-1.0.3.tar.gz

        $ ls

        $ ln -s hadoop-1.0.3 hadoop #/home/stat/hadoop 가 hadoop의 설치디렉토리가 된다.




2) hadoop 환경설정  

 hadoop-env.sh 설정

 ----------------------------------------------------------------------------------------

 : Hadoop이 실행하는 모든 프로세스에 적용되는 시스템 환경 값에 대한 스크립트

   환경변수에 대해서 시스템 변수로 등록해 사용하는 방식이 아니라, 

   이 파일에 모든 환경 변수를 설정하고 이 파일을 전체 클러스터 노드에 복사해 사용함

 ----------------------------------------------------------------------------------------

        $ vi /home/stat/hadoop/conf/hadoop-env.sh

        ###############################################################

        # The maximum amount of heap to use, in MB. Default is 1000.

        export HADOOP_HEAPSIZE=2000

        

        # JAVA HOME

        export JAVA_HOME=/usr/lib/jvm/java-7-oracle

        export HADOOP_HOME=/home/stat/hadoop

        export HADOOP_SLAVES=${HADOOP_HOME}/conf/slaves

        export HADOOP_LOG_DIR=${HADOOP_HOME}/logs

        # for R

        export LD_LIBRARY_PATH=/home/stat/lib/R/i686-pc-linux-gnu-library/2.15:$LD_LIBRARY_PATH


        # Warning: $HADOOP_HOME is deprecated.

        export HADOOP_HOME_WARN_SUPPRESS="TRUE"

        ###############################################################


 core-site.xml 설정

 ----------------------------------------------------------------------------------------

  Hadoop 설치 후 로그파일, 네트워크 튜닝, I/O튜닝, 파일 시스템 튜닝, 압축 등과 같이 기본적인 하부 시스템 설정

  맵리듀스에서도 공통으로 사용

 ----------------------------------------------------------------------------------------

        $ vi /home/stat/hadoop/conf/core-site.xml

        ###############################################################

        <configuration>

         <property>

                 <name>fs.default.name</name>

                 <value>hdfs://master:9000</value>

         </property>

        </configuration>

        ###############################################################


 hdfs-site.xml 설정

 ----------------------------------------------------------------------------------------

 Hadoop파일 시스템을 위한 설정파일로 자세한 항목은 hdfs-default.xml파일을 참고

 ----------------------------------------------------------------------------------------


        $ vi /home/stat/hadoop/conf/hdfs-site.xml

        ###############################################################

        <configuration>

        <property>

          <name>hadoop.tmp.dir</name>

          <value>/home/hadoop/temp</value>

          <description>A base for other temporary directories.</description>

        </property>

        <property>

          <name>dfs.name.dir</name>

          <value>/home/stat/filesystem/name</value>

        </property>

        <property>

          <name>dfs.data.dir</name>

          <value>/home/stat/filesystem/data</value>

        </property>

        <property>

          <name>dfs.replication</name>

        <value>3</value>

        </property>

        </configuration>

        ###############################################################


 mapred-site.xml 설정

 ----------------------------------------------------------------------------------------


 ----------------------------------------------------------------------------------------

        $  vi /home/stat/hadoop/conf/mapred-site.xml

        ###############################################################

        <configuration>

           <property>

              <name>mapred.system.dir</name>

              <value>/home/stat/filesystem/mapreduce/system</value>

           </property>

           <property>

              <name>mapred.local.dir</name>

              <value>/home/stat/filesystem/mapreduce/local</value>

           </property>

           <property>

              <name>mapred.job.tracker</name>

              <value>master:9001</value>

           </property>

           <property>

              <name>mapred.child.jvm.opts</name>

              <value>-Xmx1g -Xms1g  -Djava.library.path=/usr/local/lib/R/site-library </value>

           </property>

        </configuration>

        ###############################################################


- masters / slaves 노드 추가하기

 ----------------------------------------------------------------------------------------

masters: 세컨드리 네임 노드가 실행될 서버지정

slaves: 데이터 노드가 실행될 서버지정

hadoop-metrics.properties - Hadoop에서 각 기능별(파일시스템, 맵리듀스)로 모니터링 데이터를 수집하는 방식에 대한 설정


./conf/masters 파일을 열어 master 컴퓨터의 ip 혹은 호스트명을 입력한다.

※ master 라고 입력한다.

./conf/slaves 파일을 열어 slave 컴퓨터들의 ip 혹은 호스트명을 입력한다.

※ ip를 입력해도 되지만 /etc/hosts에 slave 호스트명을 추가하고 호스트명을 입력하는 것도 좋은 방법이다.

 ----------------------------------------------------------------------------------------


$ vi /home/stat/hadoop/conf/masters 

        master


$ vi /home/stat/hadoop/conf/slaves 

        slave01

        slave02

        slave03

        slave04

        slave05



3) hadoop 설정파일 복사 (master에 설정한 파일을 slave로 복사)

- master 서버

        ###############################################################

        $ cd /home/stat/

        $ tar -cvzf hadoop.tgz ./hadoop-1.0.3

        ###############################################################


-slave에 디렉토리생성


- 생성된 hadoop.tgz를   /var/www로 복사

        ###############################################################

          $ sudo cp /home/stat/hadoop.tgz /var/www/hadoop.tgz

        ###############################################################


- slave 서버

        ###############################################################

        $ cd /home/stat

        $ wget http://203.247.248.250/hadoop.tgz

        $ tar -xvzf hadoop.tgz

        $ ln -s hadoop-1.0.3 hadoop

        ###############################################################



4) hadooop 실행

- namenode 포맷(master 에서 실행)

        $ ./hadoop/bin/hadoop namenode -format


- hadoop 서버시작(master 에서 실행: 작업디렉토리는 "/home/stat"라고 가정)

        $ ./hadoop/bin/start-all.sh


- slave 서버: slave 서버로그 확인

        $ cd /home/stat/hadoop/logs

        $ ls

                hadoop-webservice-datanode-slave-01.log

                hadoop-webservice-datanode-slave-01.out

                hadoop-webservice-tasktracker-slave-01.log

                hadoop-webservice-tasktracker-slave-01.out

        

- hadoop 실행

        $ ./start-all.sh

- hadoop 종료시

        $ ./hadoop/bin/stop-all.sh 


- hdfs 실행

        $ ./start-dfs.sh

- mapreduce 실행

        $ ./start-mapred.sh



- http://203.247.248.250:50030/ 에서 mapreduce 설정 확인가능

- http://203.247.248.250:50070/ 에서 hdfs 설정 확인가능



5) test


- dfs 디렉토리 생성

        $ ./home/stat/hadoop/bin/hadoop dfs -mkdir input


- dfs 파일 input

        $ vi test.txt

        $ ./hadoop dfs -put test.txt input2


- dfs 파일 조회

        $ ./hadoop dfs -ls input2


-dfs 파일 삭제

        $ ./hadoop dfs -rm input/test.txt

        Deleted hdfs://master:9000/user/hadoop/input/data.log

        $ ./hadoop dfs -ls input

        $ ./hadoop dfs -rm - output


        $ ./hadoop dfs -put test.txt input


-word count

        $ ./hadoop dfs -put test.txt input2

        $ ./hadoop jar ../hadoop-examples-1.0.3.jar wordcount input2 output3

        $ ./hadoop dfs -copyToLocal output3 aaa

        $./hadoop dfs -copyToLocal out_pois aaa



Prerequisites for Installing RHIPE

1.A working Hadoop cluster

2.R installed as a shared library

3.Google protocol buffers

4.Environment variables



- Prerequisite 1: Hadoop


- Prerequisite 2: R as a Shared Library

        # R 제거

        $ sudo apt-get remove r-base-core


        # R 설치: 아래 참고하여 설치할 것

        ####################################################

        $ wget http://infostat.dongguk.ac.kr/CRAN/src/base/R-2/R-2.15.1.tar.gz

        $ tar -xzf R-2.15.1.tar.gz

        $ cd R-2.15.1

        # need to build shared library (--enable-R-shlib)

        $ ./configure --enable-R-shlib # --prefix=...

//오류시 아래 패키지 설치 후 재시도

        $ sudo apt-get install libX11-dev

        $ sudo apt-get install libxt-dev

//#설치

        $ sudo make

        $ sudo make install

        ####################################################


- Prerequisite 3: Protocol Buffers


        ####################################################

        # Download Protobuf from here.

        $ wget http://protobuf.googlecode.com/files/protobuf-2.4.1.tar.gz

        # Decompress downloaded file.

        $ tar -xzf protobuf-2.4.1.tar.gz

        $ cd protobuf-2.4.1

        # configuration

        $ sudo ./configure --prefix /usr

        # Set Environment Path

        $ export LD_LIBRARY_PATH=/usr/local/lib

    # install

        $ sudo make

        $ sudo make install



$sudo vi /etc/profile

---맨뒤에 아래 추가

PATH=$PATH:/home/stat/hadoop/bin:/home/stat/R-2.15.1/bin

export PATH

----


$source /etc/profile 해주시면 적용됩니다. 


        ####################################################

        5.Install binutils-gold for (Ubuntu 11.10).

        This package is used to resolve link error when compiling RHIPE in (Ubuntu 11.10).

        I found an article that describes linker of Ubuntu is changed slightly in order of parameters, therefore, RHIPE makes many many link errors.

        To install, just follow the command if binutils-gold is not installed.

        $ sudo apt-get install binutils-gold


- Prerequisite 4: Environment Variable


        $ sudo vi /etc/R/Rprofile.site

        ####################################################

        Sys.setenv(JAVA_HOME="/usr/lib/jvm/java-7-oracle")

        Sys.setenv(HADOOP_HOME="/home/stat/hadoop")

        Sys.setenv(HADOOP_BIN="/home/stat/hadoop/bin")

        ####################################################



- Installing Rhipe

        ####################################################

        $ wget https://github.com/downloads/saptarshiguha/RHIPE/Rhipe_0.67.tar.gz

        또는

        $ wget http://datamining.dongguk.ac.kr/hadoop/Rhipe_0.67.tar.gz

        $ tar -xzf Rhipe_0.67.tar.gz

        $ sudo R CMD INSTALL Rhipe_0.67.tar.gz

        ####################################################


#아래의 에러발생시

g++ -I/usr/share/R/include -DNDEBUG      -fpic  -O3 -pipe  -g  -I.  -O3 -pipe  -g   -DHAVE_UINTPTR_T    `/usr/lib/R/bin/R CMD config --cppflags` `pkg-config --cflags protobuf` -c signal.cc -o signal.o

/bin/bash: pkg-config: 명령어를 찾을 수 없음


$ sudo apt-get install pkg-config


######

네이티브 스내피 라이브러리를 하둡으로 복사


        wget http://anova.dongguk.ac.kr/snappy-1.0.5.tar.gz

        tar -xzf snappy-1.0.5.tar.gz

        cd snappy-1.0.5

    ./configure --enable-shared

        sudo make

        sudo make install


        cp /usr/local/lib/libsnappy.* /home/stat/hadoop/lib/native/Linux-amd64-64

        cp /usr/local/lib/libsnappy*.* /home/stat/hadoop/lib/native/Linux-i386-32

Technical Note/MOBILE PERFORMANCE

1 Intro


일전에 어떤 기업에서 기술면접을 본 적이 있다. 그 때 면접관이 물어봤던 물음 중에 하나가 “안드로이드 플랫폼에서 메모리 누수가 일어나는 경우와 그것을 어떻게 관리할지”에 대한 것이었다. 당시에는 솔직히 잘 몰라서 아주 원론적인 답만 했다. 그게 한동안 계속 기억에 남아서 날 찜찜하게 만들었다.


메모리 누수 문제는 어떤 언어나 플랫폼을 쓰던 꼭 집고 넘어가야 할 문제이다. 나의 경우엔 C와 같이 프로그래머가 직접 메모리를 관리하는 경우에만 익숙해져 있다보니 자동으로 메모리를 관리한다는 Java 같은 언어에서는 어떤 문제가 발생하는지 정확히 알지 못했다.


여담이지만 특정기능을 시스템 차원에서 지원한다는 것이 마냥 좋지만은 않은 것 같다. 뭔가가 ‘자동’으로 이루어진다는 말은 그걸 쓰는 사람이 필요에 따라 그 기능에 직접 개입할 수 없다는 뜻도 되기 때문이다. 설사 직접 개입할 수 있는 길이 있다 하더라도 보통 그런 접근법은 권장되지 않는다. 그 기능의 작동 플로우에 녹아들어 같이 휩쓸려가는 방식이 권장된다. 이런 관계로 자동으로 이루어지는 그 작동 방식을 알아야한다. 모르면 잘못 사용할 가능성이 높다는 것이다. Java의 Garbage Collection도 딱 이런 경우인데, C에서 직접 메모리를 관리하면서 주의해야할 부분과는 또 다른 방식으로 신경을 쓸 수 밖에 없는 것 같다.


암튼 모순적이게도 Java 세상에서도 프로그래머가 직접 메모리 관리에 대해 신경써야 하는 상황이 있으니 그에 대해 한번 정리해보고자 한다.


2 Java에서의 메모리 누수


원론적으로 말하자면 Java의 Garbage Collector(이하 GC)가 제대로 작동할 겨우 메모리 누수가 생길 수 없다. 왜냐하면 GC가 특정 조건을 trigger로 작동하면서 아무도 참조하지 않는 (힙의 특정영역을 점유하고 있을)객체는 회수하기 때문이다1. 반대로 말하자면 회수가 안된 객체는 누군가에 의해 분명 참조되고 있다는 뜻이다. 만약 룰이 깨진다면 그것은 해당 JVM 구현의 버그일 것이다.


그렇다면 Java에서 메모리 누수란 무엇일까? 위의 전제에서 힌트가 있다. 즉 누군가에 의해 참조되고 있는 그 객체가 진정 쓸모있냐 없냐에 달린 것이다. 쓸모없는 객체를 계속 누군가가 참조를 하고 있다면 그게 바로 메모리 누수이다.


Stackoverflow에 있는 재미있는 쓰레드에 보면 Java에서 쓸모없는 객체를 미친듯이 생성시켜 Out Of Memory Exception을 일으키는 여러 경우에 대한 예시가 나온다.


3 Android에서의 메모리 누수


안드로이드에서는 일반적인 JVM과는 달리 프로세스 하나마다 dalvik(JVM)이 하나씩 실행되기 때문에, JVM 하나에 다중 프로세스 때문에 생기는 문제에 대해 신경쓸 필요는 없어서 그나마 좀 간편하다고 하겠다2. 하지만 플랫폼의 구조적인 결함이나 버그로 인한 메모리 누수가 몇가지 알려져 있다. 알아보도록 하자.


3.1 Context 관련


이 문제는 안드로이드 공식 블로그 글에 원인과 해결책이 잘 나와있다. 간단히 말하면 일정한 생명주기를 가지는 Activity 내에서 View 를 생성할 때 Context 즉 해당 Activity 자체를 인자로 넘기는데, 화면 방향전환과 같이 Activity 재생성이 일어나는 경우 관련된 모든 객체들의 참조를 끊지 않으면 Activity 객체가 사용하던 메모리가 회수되지 않아 누수가 발생한다는 것이다.


이 문제는 플랫폼 설계상 어쩔 수 없이 생길 수 있는 것인 듯 하다. 플랫폼 구조를 뜯어고치지 않는 이상 응용프로그래머가 주의하여 프로그래밍 할 수 밖에 없는 상황이라 하겠다.


그럼 해결 방법은 무엇일까? 몇가지가 있다.


Activity Context 대신 Application Context를 사용할 것을 고려하라. Application Context 객체는 Application 단위의 생명주기를 가진다.

Activity Context를 Activity에서 쓸 경우, Activity 생명주기와 싱크를 맞추어라.

만일 Activity의 sub-class를 정의하여 사용한다면, sub-class에서 상위 Activity를 참조하는 경우를 되도록 만들지 마라. 대신 sub-class를 static으로 정의하고 해당 클래스가 Activity와WeakReference 를 갖도록 하라.

3.2 Bitmap 관련3


안드로이드 버전 2.3.3(API Level 10) 이전의 경우 Bitmap 의 픽셀 데이타를 native heap에 저장했다고 한다. 이로 인해서 Bitmap 객체가 GC를 통해 메모리 회수되지 않고 자꾸 쌓여서 OOM Exception을 일으키는 경우이다. 어떻게 보면 말도 안되는 일인데, 이를 해결하기 위해서 Bitmap의 recycle() 4이란 함수를 호출하라고 친철히 설명하고 있다. 최근 버전들은 이 문제가 해결되어(native heap을 쓰지않고 Dalvik VM heap으로 바꾸었다함) 참조변수를 null 로 바꾸기만 해도 충분하다고 한다.


3.3 기타


그 외에도 WebView5 나 MapView6 등에서 누수가 일어나는데 딱히 해결책이 없는 모양이다. 그나마 누수의 크기가 크지 않아서 조심하면서 쓰는 수 밖에 없단다.(뭐 이래~!)


4 마무리


Memory Leak이란 결국 해당 프로그램이 메모리(heap) 부족으로 원하는 시간만큼 실행되지 못할 때 문제가 된다. 잠재적인 위험을 가지고 있지만, 즉 누수가 조금씩 일어나지만 메모리 부족이 생기기 이전에 실행이 끝나고 프로세스가 정상적으로 죽는 경우라면 사실 문제될 이유가 없다. 하지만 그렇게 제한적인 프로그램이 활용도가 높을리는 없을꺼다. 따라서 프로그래머는 메모리 누수를 신경써야 한다. 아주 많이.


5 References


Memory Management in the Java HotSpot Virtual Machine

Java Reference와 GC

Bitmap.recycle()은 가급적 호출해 주는 편이 좋다. (Android 2.x 버전)

안드로이드 메모리 누수 줄이기

https://docs.google.com/present/edit?id=0AUhbwUh9azXLZGZnNnpnYzhfMzFjYnp2NzRjNg

Footnotes:


1 더 정확히 말하면 레퍼런스의 Root Set에 해당객체를 직접적 혹은 간접적으로 참조하는 변수가 없다면 그 객체는 garbage collecting 시에 회수된다.


2 시스템의 아래로 내려가면 결국은 Linux 프로세스 위에 dalvik이 하나씩 떠 있는 상황이라 특정 프로세스에서 메모리릭이 발생하여 그 프로세스가 죽는다고 해도 다른 프로세스에는 영향이 없다.


3 Issue 8488: 'bitmap size exceeds VM budget' if Activity is restarted {includes test demo!}


4 이 함수는 Bitmap 이 객체화 될때 native heap에 할당한 픽셀 데이타를 free 시킨다.


5 http://stackoverflow.com/questions/3130654/memory-leak-in-webview


6 Issue 2181: Memory leak in system when using MapView

Technical Note/ANDROID

출처 : http://developer.android.com/tools/debugging/debugging-ui.html


Optimizing Your UI ( UI 최적화하기 )


layout 때문에 앱이 느려질 수 있다.

layout 에 관련된 debug 는 Hierarchy Viewer 와 lint tools 를 통해 할 수 있다.


Hierarchy Viewer 는 layout 의 계층도를 보여주며, 각 node 가 얼마나 성능을 내는가를 볼 수 있다.

그리고 Pixel Perfect window 를 통해 확대해 볼 수도 있다.


lint 는 static code scanning tool 로 일반적으로 발생하는 coding problem 을 잡아준다.

layout file 이나 다른 resource directory 에서 손쉽게 문제를 찾아 성능이슈를 해결할 수 있다.




Hierarchy Viewer 사용하기


시큐리티 이슈가 있어서, Hierarchy Viewer 는 오직 developer 모드로 빌드된 단말에서만 작동한다.


독자 : 뭐야 말짱 황이자나?

필자 : 아니다. (느리지만, 답답하지만) 에뮬레이터로 하면 된다.


1. 앱을 실행시키고 terminal 에서 hierarchyviewer 를 입력하여 실행시킨다.

위치는 <sdk>/tools/ 에 있다.


2. 처음 보는 화면은 device 의 종류이다.

그곳에서 트리를 따라가면서 hierarchy 를 보고 싶은 activity 를 찾아들어간다.


3. 그곳에서 view hierarchy 를 볼 수 있고, pixel perfect window 를 이용하여 뷰를 확대할수도 있다.



View Hierarchy Window



VIew object 는 rendering performance data 도 가지고 있다.


4개의 패널이 있다.


1. Tree View


왼쪽에 위치해있으며, view hierarchy 를 tree 형태로 보여준다.

패널을 zoom 하기 위해서는 패널 아래쪽 slider 를 이용할 수 있고, 마우스 휠을 이용해도 된다.

패널내에서 이동을 하고 싶으면 마우스 클릭 후 드래그 하면 된다.


특정노드를 찾아 highlight 하고 싶으면 "Filter by class or id:" 란에 filter text 를 입력하면 된다.

매칭되는 노드는 갈색에서 밝은 푸른색으로 변형된다.


TreeView 의 screenshot 을 "Save AS PNG" 를 통해 저장할 수도 있다.

"Capture Layers" 를 통하면 Adobe Photoshop ( PSD ) 로도 저장할 수 있다. 이 경우 모든 view 가 layer 로 구분되어 저장된다.

( 호! 좋은데? )



2. Tree Overview


우상단에 위치해있으며, 전체 트리의 현재 포지션 등을 간단하게 보여준다.

드래그나 클릭을 통해 쉽게 위치를 이동할 수 있다.

Technical Note/ANDROID

안드로이드의 앱의 퀄리티가 날이 갈 수록 높아지고 있는 만큼 이런 퀄리티 높은만큼 뷰의 구조가 점점더 복잡해지고 있다. 뷰의 구조가 복잡 할 수록 앱이 실행하는데 그 만큼의 영향을 미치게되어 사용자로하여 느린 반응을 보일 수가 있다. 이런 뷰의 구조를 최대한 줄이기 위해 최대한 노력해야 한다. ADT에서 훌륭한 Hierarchy Viewer를 통해 View의 구조를 도면같이 펼쳐서 보여주는 툴이 있다. 하지만 구조가 복잡하면 복잡해질 수록 보기에는 다소 무리가 있는 경험들이 있을 것이다.

이런 구조를 좀더 쉽게 파악할 수 있도록 3D로 표현 해주는 Droid Inspector이라는 툴이있다

Droid Inspect의 장점


- 3D로 View구조를 파악 할 수 있다.

- Overdraw를 찾아 낸다.

- 개별 View의 bounds를 볼 수 있다.

- DDMS plugin으로 지원 한다..

- View 계층을 숨기거나 보일수 있다.

- Web 파일로 추출 가능하다.




1 ··· 3 4 5 6 7 8 9 ··· 27
블로그 이미지

zzikjh