2016년 12월 7일 수요일

JVM 메모리를 넘는 Huge Excel 파일 입출력

https://poi.apache.org/spreadsheet/limitations.html

  위의 링크 내용 중 메모리에 관한 내용만을 추리면 아래와 같다.


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

디폴트 POI 클래스들을 쓰는 것만으로는 memory의 한계가 있다. 
그러므로 매우 큰 Excel 파일을 읽거나 쓰려고 한다면 Out of memory를 만나게 될 것이다.
Main memory에 Excel 처리를 위한 객체를 올려서 작업하는 스타일 때문인데, 이것을 극복하기 위한 방법이 있다.

* 매우 큰 파일을 쓰기 위한 SXSSFWorkbook이 있다. 이것은 data를 streaming으로 쓸 수 있도록 도와준다.

* 매우 큰 파일을 읽기 위해서는XLSX2CSV 을 참고해 볼 수 있다. Excel 파일을 streaming 형태로 읽을 수 있도록 하며, 읽어들이는 정보의 한계가 있으므로 필요할 경우 수정해서 사용할 수 있다.

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

  위의 내용 중 매우 큰 Excel 파일 읽기에 대한 경험이 있다. 소스 코드(XLSX2CSV)를 참고로 하여, Excel(XLSX)를 파싱하면서 몇가지 문제가 겪었다.

  일단 Excel(XLSX) 파일은 XML 파일들과 그 외 메타데이터를 포함한 압축파일이다. (그래서 .xlsx 파일을 확장자만 .zip 파일로 변경하면 압축해제를 할 수 있기도 하다.)
  아무튼 XLSX2CSV 예제는 엑셀을 XML 형태로 읽어 들여 element 별로 처리를 해서 데이터를 읽도록 되어 있다.
  XML Parsing 라이브러리를 사용해서 streaming으로 읽기 작업을 처리할 수 있게 된 것인데, 그러면서 생긴 제약이 Excel에서 비어 있는 셀에 대해서 xml이 비어있을 수 있는 문제가 발생하게 된다. 그래서 실제로 사용하면서 필요했던 내용들을 어떻게 보면 하드코딩 방식으로 때워가며 사용했었다.

  가장 일반적인 형태로 xml의 element가 비어 있는 시나리오가 3가지가 있었고, 그러한 상황에 대처하기 위해 method를 추가하는 식으로 작업을 했다.

  매번 재작업하기 보다는 미리 정리해놓고 사용할 수 있었으면 좋겠다는 생각이 들어서 github repository에 올려놓았다.

https://github.com/sungpeo/large-xlsxtocsv


Java finalizer

GC 공부하면서 Finalize에 대한 설명을 들었는데,
난 그게 뭔지 여태 몰랐던 거였음. 소름.

link : http://www.javatpoint.com/difference-between-final-finally-and-finalize


There are many differences between final, finally and finalize. A list of differences between final, finally and finalize are given below:
No.finalfinallyfinalize
1)Final is used to apply restrictions on class, method and variable. Final class can't be inherited, final method can't be overridden and final variable value can't be changed.Finally is used to place important code, it will be executed whether exception is handled or not.Finalize is used to perform clean up processing just before object is garbage collected.
2)Final is a keyword.Finally is a block.Finalize is a method.


2016년 12월 6일 화요일

G1 GC

G1 GC는 Generational GC의 단점을 보완한다!

-> CMS GC를 대체하기 위한 Low-Pause & Concurrent Garbage Collector 임.
-> Stop-The-World에 의한 Pause Time을 예측할 수 있음(Soft Real-Time)
-> Compaction을 동반하므로, Fragmentation을 줄일 수 있음
-> 세대별(Generational)로 객체를 관리하며 Parallel/Concurrent 수행방식은 기존의 Collector아 비슷하나, Young영역과 Old영역의 구분을 특정하지 않는 일정한 크기의 Region으로 관리됨

주요 point :
*예측
*Compaction

- - - - - - - - - -
단계 :

Evacuation Pause : Minor GC와 동일한 작업으로, Young 영역을 G 한다. (STW 발생)
Concurrent Cycle : Old 영역을 GC하기 위한 사전 단계로, live 객체를 Marking 한다.
Mixed GC : Old 영역에 대한 GC를 마무리하는 단계로, Young 영역과 Old 영역을 동시에 GC한다.


- - - - - - - - - -
Evacuation Pause
 - 대부분의 단계가 Parallel로 수행
 - STW 발생

Ext Root Scanning : 각 GC Thread들이 Global, Register, Thread stack 등에서 root 노드 검색
Update RS : Remembered Set* 정보를 갱신
Scan RS : 업데이트 된 remembered Set 정보를 기반으로 Reference를 가진 객체들를 탐색
Object Copy : Scan RS에서 탐색한 객체들을 다른 Region으로 복사. Eden -> Survivor , Survivior -> Old
Termination : 종료 Thread가 다른 Thread 들의..

*용어설명
*Remembered Set : 해당 Region내의 각체로 Refernece하는 객체들의 목록
*Collection Set : GC시 수집될 Region들의 목록

- - - - - - - - - -
Concurrent Cycle
 - IHOP에서 지정한 수치가 넘어가면 Trigger됨.
 - initial-mark 이후 수행됨 (initial-mark는 Young GC시 함께 수행)

Root Region Scan
Concurrent mark
Remark
Cleanup : Region 내 살아있는 객체 정보를 갱신하고, Empty region을 식별(STW 발생)
Concurrent Cleanup : Empty Region을 Reset하고, 미사용 영역에 추가함(Empty Region이 없으면 Skip)

*용어설명
*IHOP(InitiatingHeapOccupancyPercent) : Heap이 일정 비율만큼 차지하면 Marking을 수행하도록 하는 옵션. 기본값은 45(%)

- - - - - - - - - -
Mixed GC
 - Evacuation Pause(Young GC)와 동일
 - Young 영역과 Old 영역이 동시에 수집됨
 - 여러 번으로 나누어 수행됨
 - STW 발생
(살아있는 객체가 적은 Young/Old 영역들이 GC 및 Compaction의 대상이 됨(GC 목표시간/빈도 반영)

Ext Root Scanning
Update RS
Scan RS
Object Copy
Termination

- - - - - - - - - -
G1 GC를 요약하면 다음과 같다 !
 - JAVA 1.7부터 정식 지원
 - 여러개의 영역(Region)으로 나누어 관리되며, 각 영역의 역할(Eden/Young/Old)은 쉽게 변경이 가능
 - MinorGC는 Evacuation Pause로 수행, MajorGC는 최대한 Application과 동시에 수행할 수 있도록 Concurrent Cycle과 Mixed GC(Evacuation Pause)로 구부하여 수행됨
 - 각 Region에는 살아있는 객체 정보를 가지고 있으며, 이것을 바탕으로 먼저 Garbage 되어야 하는 Region을 결정
 - GC 수행 시 Compaction을 수행함으로 인해 Fragmentation을 줄여 연속된 메모리 할당에 효율적
 - 객체 크기가 Region의 1/2보다 큰 경우, humongous 영역으로 관리

장점 !
 - 상대적으로 GC 성능 우수
 - 수행시간 예측 가능, STW 지속시간을 줄일 수 있음
 - FullGC 지속시간 및 빈도를 줄일 수 있음

- - - - - - - - - -


2016년 7월 25일 월요일

dfs 알고리즘 : NQueen


package N_Queen;

import java.util.Scanner;

public class source {
static int n;
static int arr[][] = new int[15][15];
static boolean chk[] = new boolean[15];
public static void main(String[] args){

Scanner sc = new Scanner(System.in);
n = sc.nextInt();
System.out.println(back(1));
}
static int back(int k){
if (k==n+1) return 1;
int total=0;
for (int i=1;i<=n; i++){
if(chk[i]) continue;
boolean impossible = false;
for(int j=1; j<k; j++){
if (i-j>0 && arr[k-j][i-j]==1) impossible = true;
if (i+j<=n && arr[k-j][i+j]==1) impossible = true;
}
if(impossible) continue;
arr[k][i] = 1;
chk[i] = true;
total += back(k+1);
arr[k][i] = 0;
chk[i] = false;
}
return total;
}
}

2016년 2월 5일 금요일

composite key in hive with hbase

CREATE TABLE hbase_table_3(key string, value2 int)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES (
"hbase.columns.mapping" = ":key,a:b"
);


INSERT OVERWRITE TABLE hbase_table_3
SELECT coalesce(concat(stock_symbol,'-',year(trade_date)),'NULL'), count(*)
FROM stock_trade
group by coalesce(concat(stock_symbol,'-',year(trade_date)),'NULL');

2016년 1월 16일 토요일

Fitbit REST API : Getting an access_token

After Obtaining User's Consent,
Fitbit.com will redirect to your server.

This is a code for the server.

I'll store access_token and refresh_token.




@RequestMapping(value="/restTest", method=RequestMethod.GET)
public String restTest(@RequestParam(value="code", required=false) String code) {
    StringBuilder sb = new StringBuilder();
    if(code!=null) {
        HttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(REST_URL_TO_GET_TOKEN);
        httpPost.setHeader("Authorization",AUTH_APPID_APPSECRET);
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("client_id", CLIENT_ID));
        nvps.add(new BasicNameValuePair("grant_type", "authorization_code"));
        nvps.add(new BasicNameValuePair("redirect_uri", REDIRECT_URL));
        nvps.add(new BasicNameValuePair("code", code));
        StringBuilder contentSb = new StringBuilder();
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nvps));
            HttpResponse response = httpclient.execute(httpPost);
            HttpEntity resEntity = response.getEntity();
            if (resEntity != null) {
                BufferedReader rd = new BufferedReader(new InputStreamReader(
                        response.getEntity().getContent()));
                String line = null;
                while ((line = rd.readLine()) != null) {
                    contentSb.append(line);
                }
            }
            httpPost.abort();
        } catch (Exception e) {
            sb.append("Exception::" + e.getStackTrace().toString());
        }
        sb.append(contentSb.toString());

    } //if(code!=null)
    return sb.toString();
}




Authorization Header Example

This example assumes that the code URI parameter value in the callback URI was 1234567890.
POST https://api.fitbit.com/oauth2/token
Authorization: Basic Y2xpZW50X2lkOmNsaWVudCBzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded

client_id=22942C&grant_type=authorization_code&redirect_uri=http%3A%2F%2Fexample.com%2Fcallback&code=1234567890
Example Response:
{
    "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MzAzNDM3MzUsInNjb3BlcyI6Indwcm8gd2xvYyB3bnV0IHdzbGUgd3NldCB3aHIgd3dlaSB3YWN0IHdzb2MiLCJzdWIiOiJBQkNERUYiLCJhdWQiOiJJSktMTU4iLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJpYXQiOjE0MzAzNDAxMzV9.z0VHrIEzjsBnjiNMBey6wtu26yHTnSWz_qlqoEpUlpc",
    "expires_in": 3600,
    "refresh_token": "c643a63c072f0f05478e9d18b991db80ef6061e4f8e6c822d83fed53e5fafdd7",
    "token_type": "Bearer",
    "user_id": "26FWFL"
}