Javascript 형변환 테크닉

Posted by epicdev Archive : 2012. 2. 23. 22:34
Javascript에서 형변환을 할 때 primitive type의 생성자를 사용하지 않고, 간단하게 연산자를 통해서 아래처럼 형변환이 가능하다.

  

Udacity를 소개합니다

Posted by epicdev Archive : 2012. 2. 23. 20:06


Udacity란 open course들을 제공하는 많은 사이트들 중에 하나이다.
http://www.udacity.com/

Udacity는 다른 open course 사이트들과는 다르게 Computer Science 과목들만 집중적으로 다루고 있다.
런칭한지는 그다지 오래되지 않았으나 개인적으로는 가장 기대하고 있는곳이다.

이곳을 설립한 Sebastian Thrun은 Stanford의 Computer Science 학과에서 가장 잘 나가는 교수들중 한명이며
현재 내가 대학원에서 연구하고 있는 분야의 현재 세계 1인자인 대단한 사람이다.
내가 Udacity를 가장 기대하는 이유는, Sebastian Thrun의 엄청난 학계 인맥에 있다.
Thrun의 인맥을 이용해서 유명한 교수들을 초빙하여 수업을 한다면
수업의 질이 당연히 좋아질수밖에 없다고 생각한다.

게다가 각 수업을 듣고 숙제를 하고 시험을 치고 과목을 통과하면 수료증도 준다고 한다.
수료증이 실제로 큰 의미는 없겠지만,
나같은 경우는 open course를 듣다보면
초반에 열심히 듣다가 바빠서 나중에는 그냥 때려치우는데
이를 방지하는데 도움이 될것이라고 생각한다.

그리고 open course의 가장 큰 문제인 학생과 교수의 interaction이 없다는 점을
브라우저 기반의 퀴즈나, 브라우저 내에서 동작하는  Python interpreter를 통한 프로그래밍 퀴즈를 통해서
문제를 해결하고 있다.
특히나 퀴즈의 경우는 비디오 인식 기술을 사용해서 교수가 화면에 특정 형태의 form을 그려주면
그 form을 기반으로 퀴즈가 저절로 생성되게 된다.
그렇게 생성된 퀴즈가 학생들에게 주어지기 때문에
학생들의 입장에서는 수업의 컨텍스트를 잃지 않으면서 퀴즈를 풀 수 있어 수업에대한 집중도가 더 높아지고
교수의 입장에서는 따로 퀴즈를 만들지 않아도 되기 때문에 편리하다.
이 기술의 데모는 아래의 링크에서 볼 수 있다.
http://www.youtube.com/watch?feature=player_detailpage&v=SkneoNrfadk#t=321s



Stack overflow 프레임워크를 사용한 포럼도 존재해서 학생들간의 discussion도 가능하며
실제로 매우 활발한 discussion이 수업들마다 진행되고 있다.
또한 office hour도 있어서 특정 시간에 포럼을 통해서 교수와 질의응답도 가능하다.



현재 Udacity에는 CS101과 CS373이 있는데
101은 검색엔진 만들기이고
373은 무인자동차 만들기이다



373의 경우는 세계적인 무인자동차 권위자인 Thrun이 직접 수업을 해서 많이 기대가 되는 수업이다.
아직은 101과 373 두개의 수업밖에 없지만
개설예정 과목들을 보면 Computer Science의 전반적인 핵심과목들을 개설할 예정인듯하다.

Udacity가 Computer Science를 접해보지 못한 일반인들에게도 많은 도움을 주겠지만
Computer Science 전공자인 나같은 사람에게도
평소에 관심은 있었지만 수강을 못했던 혹은 개설하지 않아서 수강하지 못했던 과목들을
수강할 수 있기 때문에 전공자 비전공자 모두에게 많은 도움이 될것이라 생각한다.
  

함수의 세가지 필수조건

1. 함수가 호출되었던 지점으로 복귀 가능
2. Caller와 Callee간의 데이터 교환 가능
3. 중첩된 호출이 가능 (함수 내에서의 함수 호출)

스택프레임을 사용하여 위의 조건을 구현함


출처:  http://www.winapi.co.kr/clec/cpp2/16-1-3.htm 
 

16-1-다.호출 규약

앞 항에서 Add 함수의 어셈블리 코드를 통해 스택 프레임의 실제 모양을 확인해 보았다. 인수는 뒤쪽부터 순서대로 전달하며 인수 전달에 사용한 스택 영역은 호출원이 정리했는데 이는 C/C++ 언어의 기본 호출 규약인 __cdecl의 스택 프레임 모양일 뿐이다. 호출 규약이 바뀌면 스택 프레임의 모양과 관리 방법도 달라질 수 있다.

호출 규약은 호출원과 함수간의 약속이므로 양쪽이 다른 형태로 약속을 할 수도 있는 것이다. 그렇다면 __cdecl이 아닌 다른 호출 규약은 어떻게 스택 프레임을 작성하는지 차이점을 분석해 보자. 호출 규약에 따라 인수를 전달하는 방법과 스택의 정리 책임, 함수의 이름을 작성하는 방법이 달라진다.

 

호출 규약

인수 전달

스택 정리

이름 규칙

__cdecl

오른쪽 먼저

호출원

_함수명

__stdcall

오른쪽 먼저

함수

_함수명@인수크기

__fastcall

ECX, EDX 우선 전달나머지는오른쪽 먼저

함수

@함수명@인수크기

thiscall

오른쪽 먼저, this 포인터는 ecx 레지스터로 전달된다.

함수

C++ 이름 규칙을 따름.

naked

오른쪽 먼저

함수

없음

 

리턴값을 돌려 주는 방식도 호출 규약에 따라 달라질 수 있는데 다행히 현존하는 모든 호출 규약의 리턴 방식은 동일하다. 4바이트의 값을 돌려줄 때는 eax 레지스터를 사용하며 8바이트의 값을 리턴할 때는 edx:eax 레지스터 쌍을 사용한다. 8바이트를 초과하는 큰 리턴값, 예를 들어 구조체 등은 임시 영역에 리턴할 값을 넣어 두고 그 포인터를 eax에 리턴한다.

__stdcall

Add 함수의 호출 규약을 __stdcall로 바꿔 보자. __stdcall은 윈도우즈 API 함수들의 기본 호출 규약이며 비주얼 베이직도 이 호출 규약을 사용한다. __cdecl과 인수를 전달하는 방법은 동일하되 인수 전달에 사용된 스택을 정리하는 주체가 호출원이 아니라 함수라는 점이 다르다. Add 함수의 호출 규약을 바꾸기 위해 다음과 같이 수정해 보자.

 

int __stdcall Add(int a, int b)

{

     int c,d,e;

     c=a+b;

     return c;

}

 

함수 이름앞에 __stdcall 키워드를 삽입하면 이 함수는 __stdcall 호출 규약을 사용한다. main에서 함수를 호출하는 부분이 다음과 같이 변경된다.

 

push 2

push 1

call Add

result=eax

 

인수를 스택에 밀어 넣는 것과 인수를 푸시하는 순서는 동일하다. 단, call Add 다음에 add esp,8 코드가 없어 함수가 리턴된 후에 인수 전달에 사용한 스택을 복구하지 않는다는 점이 __cdecl과 다르다. 인수 전달에 사용한 영역은 이제 Add 함수가 직접 정리한다. 이 함수의 접두, 본체는 __cdecl과 동일하며 접미 부분이 다음과 같이 변경된다.

 

push ebp

....

ret 8

 

복귀 코드가 ret에서 ret 8로 바뀌었으며 복귀하면서 esp를 8만큼 증가시킨다. 이 코드에 의해 함수는 실행을 마치고 복귀함과 동시에 인수 영역을 해제한다. Add 함수 자신이 복귀하면서 스택을 정리하므로 호출원에서는 스택을 정리할 필요가 없다. 호출원은 인수를 순서대로 스택에 푸시한 후 함수만 호출하면 된다.

__cdecl과의 차이점

__cdecl과 __stdcall의 가장 큰 차이점은 스택 정리 주체가 누구인가하는 점인데 사실 이 차이점이 컴파일된 결과 코드에 미치는 영향은 별로 없다. 스택 정리 주체와는 상관없이 스택은 항상 호출 전의 상태로 복구되며 프로그램의 동작도 완전히 동일하다. 실행 속도는 거의 차이가 없으며 프로그램의 크기는 비록 무시할만한 수준이기는 하지만 __stdcall이 조금 더 작다. 왜냐하면 함수를 여러 번 호출하더라도 스택을 정리하는 코드는 함수 끝의 접미에 딱 한 번만 작성되기 때문이다. 반면 __cdecl은 호출원이 스택을 정리하므로 호출할 때마다 정리 코드가 반복되어 프로그램 크기가 조금 더 커진다.

또 다른 중요한 차이점은 가변 인수 함수를 만들 수 있는가 아닌가 하는 점이다. __stdcall은 함수가 직접 스택을 정리하기 때문에 가변 인수 함수를 지원하지 않는다. 함수 접미에 스택 정리 코드를 작성하려면 인수의 총 크기를 미리 알아야 하는데 가변 인수 함수는 전달되는 인수 개수가 가변이므로 이 크기가 고정적이지 않아 접미에서 스택을 직접 정리할 수 없다. 컴파일러가 접미의 ret n 명령에 대해 n을 결정할 수 없는 것이다.

이에 비해 __cdecl은 함수가 스택을 정리할 책임이 없으며 호출원이 함수를 부를 때마다 스택을 정리한다. 함수를 호출하는 쪽에서는 인수를 몇개나 전달했는지 알 수 있으므로 실제 전달한 인수 크기만큼 스택을 정리할 수 있다. 그래서 printf나 scanf같은 가변 인수를 지원하는 함수는 모두 __cdecl 호출 규약을 사용한다. 또한 윈도우즈 API 함수의 기본 호출 규약은 __stdcall이지만 wsprintf는 예외적으로 __cdecl로 작성되어 있다.

호출 규약 중 호출원이 스택을 정리하는 것은 __cdecl밖에 없으며 그래서 가변 인수를 지원할 수 있는 호출 규약도 __cdecl이 유일하다. 가변 인수 함수를 만들려면 반드시 __cdecl 호출 규약을 사용해야 한다. 만약 가변 인수 함수를 __stdcall로 작성하면 컴파일러는 이를 무시하고 __cdecl로 강제로 바꾸어 버린다.

__fastcall

다음은 __fastcall 호출 규약을 테스트해 보자. 함수 정의부를 int __fastcall Add(int a, int b)로 수정하기만 하면 된다. 호출부의 코드는 다음과 같다.

 

mov edx,2

mov ecx,1

call Add

result=eax

 

__fastcall은 인수 전달을 위해 edx, ecx 레지스터를 사용하는데 두 개의 인수를 차례대로 edx, ecx에 대입했다. 만약 인수가 둘 이상이면 세 번째 이후의 인수는 __cdecl과 마찬가지로 스택에 밀어넣을 것이다. 인수 전달을 위해 스택을 쓰지 않고 레지스터를 우선적으로 사용하므로 인수 전달 속도가 빠르다는 이점이 있다. 함수의 코드는 다음처럼 작성된다.

 

push ebp

mov ebp,esp

sub esp,14h

mov [ebp-8],edx             // 첫 번째 인수를 지역변수로

mov [ebp-4],ecx             // 두 번째 인수를 지역변수로

mov eax,[ebp-4]

add eax,[ebp-8]

mov [ebp-0ch],eax               // c는 세 번째 지역변수가 된다.

mov eax,[ebp-0ch]

mov esp,ebp

pop ebp

ret

 

edx, ecx 레지스터를 통해 전달받은 인수 둘을 순서대로 지역변수 영역에 복사한 후 사용하는데 어차피 인수도 지역변수의 일종이므로 이렇게 해도 별 상관이 없다. VC는 fastcall 호출시 ecx, edx로 인수를 넘기기는 하지만 이를 다시 스택의 지역변수로 만드는데 이렇게 되면 fastcall을 하는 의미가 없다. 비주얼 C++은 fastcall을 형식적으로만 지원할 뿐 fastcall의 장점을 취하지는 않는데 이는 컴파일러 구현상 ecx, edx 레지스터가 꼭 필요하기 때문이다. 

스택 정리는 함수가 하는데 Add 함수의 경우 인수가 두 개 뿐이므로 인수 전달을 위해 스택을 사용하지 않았으며 그래서 정리할 내용이 없다. 만약 인수가 세 개라면 제일 끝의 ret는 ret 4가 될 것이다. 레지스터는 스택보다 훨씬 더 빠르게 동작하기 때문에 __fastcall은 이름대로 호출 속도가 빠르다. 대신 이식성에 불리하다는 단점이 있다. 이 호출 규약은 ecx, edx 레지스터를 사용하도록 되어 있는데 이 두 레지스터가 모든 CPU에 공통적으로 존재하는 것이 아니기 때문이다. 그래서 윈도우즈 API는 이 호출 규약을 지원하기는 하지만 사용하지는 않는다. 볼랜드의 델파이가 __fastcall을 사용한다.

thiscall

thiscall은 클래스의 멤버 함수에 대해서만 적용되는데 ecx로 객체의 포인터(this)가 전달된다는 것이 특징이며 나머지 규칙은 __stdcall과 동일하다. 예외적으로 가변 인수를 사용하는 멤버 함수는 __cdecl로 작성되며 이때 this는 스택의 제일 마지막에(그러므로 첫 번째 인수로) 전달된다.

이 호출 규약은 컴파일러가 멤버 함수에 대해서만 특별히 적용하는 것이므로 일반 함수에는 이 호출 규약을 적용할 수 없다. thiscall은 이 호출 규약의 이름일 뿐 키워드가 아니기 때문에 함수 원형에 thiscall이라고 쓸 수도 없다. 멤버 함수이기만 하면 컴파일러가 알아서 thiscall 호출 규약을 적용한다. 객체니 멤버 함수니 this니 하는 것들은 C++편에서 배우게 될 것이다.

__naked

__naked 호출 규약은 컴파일러가 접두, 접미를 작성하지 않는 호출 규약이다. 스택 프레임의 상태 보존을 위해 컴파일러가 어떤 코드도 작성하지 않으므로 접두, 접미는 사용자가 직접 작성해야 한다. 스택은 어셈블리 수준에서만 다룰 수 있으므로 인라인 어셈블리를 사용해야 하며 제약점도 많기 때문에 일반적인 목적으로는 사용되지 않는다.

이 호출 규약이 반드시 필요한 경우는 C/C++이 아닌 언어에서 호출하는 함수를 작성할 때이다. 예를 들어 어셈블리에서는 인수 전달에 스택을 쓰지 않고 범용 레지스터만으로도 인수를 전달할 수 있다. 이런 경우는 C컴파일러가 만들어주는 접두, 접미가 불필요하다. 또한 속도가 지극히 중요한 디바이스 드라이버를 작성할 때도 이 호출 규약을 사용한다. __naked 호출 규약을 사용하려면 함수의 정의부에 __declspec(naked)를 적어주면 된다.

여기서 알아본 호출 규약 외에도 __pascal, __fortran, __syscall 이라는 호출 규약이 있었으나 지금은 지원되지 않는다. 비주얼 C++은 과거와의 호환성을 위해 이 단어들을 키워드로 인정하기는 하지만 실제로 사용할 경우 에러로 처리한다. 이상으로 다섯 가지의 호출 규약에 대해 정리했는데 실제로 사용되고 사용자가 지정할 수 있는 호출 규약은 현실적으로 __cdecl, __stdcall 두 가지밖에 없는 셈이다.

 

  
Java에서 파일에다가 출력을 할 때 PrintWriter와 BufferedWriter를 이용할 수 있다.
(Writer를 상속하는 클래스는 BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter가 있지만 대표적인 것만 다루기로 하겠다.)

우선 PrintWriter의 경우는  print, println, printf 처럼 다양한 출력함수를 제공함으로써 파일출력을 편하게 해준다.
BufferedWriter의 경우는 버퍼를 사용하여 통해 좀 더 효율적인 파일쓰기를 지원한다.

이 두가지 방법을 마치 둘 중에 하나를 선택해야한다는 흑백논리로 생각하는 사람들이 있는데 이는 큰 오산이다.
Java의 파일 IO 클래스들은  데코레이터 패턴을 사용한다.
즉, 원시 클래스에다가 원하는 기능을 가지는 클래스를 가지고 입맛대로 꾸며서 사용할 수 있다는 것이다.

위의 코드처럼 PrintWriter를 만들어서 사용하면 PrintWriter의 장점과 BufferedWriter의 장점을 모두 이용할 수 있다.
  

Java heap의 세가지 영역

Posted by epicdev Archive : 2012. 2. 11. 05:02

Understanding Java Memory Structure

One strength of the java platform is that it shields the developer from the complexity of memory allocation and garbage collection.  We all know that java stores objects in a Heap memory.  Internally Java partitions the heap memory space logically into three areas called generations.

  1. The Young Generation
  2. The Tenured Generation
  3. The Permanent Generation

Out if these three partitions, only the young and tenured generation spaces are used for allocating memory to objects. The permanent generation space is used for holding the data needed by the virtual machine to describe objects that do not have equivalence at the Java language level.

This partitioning is done in order to improve the performance of garbage collection as performing garbage collection on the entire heap will be very expensive. Instead the architects of java decided to partition the heap space into three parts.

The Young Generation

The young generation is where space is allocated for newly created objects.  In most applications, most of the objects created are used and referenced only for a very short span of time (high infant mortality rate), for example an iterator instance is discarded as soon as the loop is complete.

The purpose of having a separate space of young generation is to maximize promptness (the time between when an object becomes dead and when the memory becomes available) and to reduce the overhead of scanning the entire heap during every garbage collection process.

Garbage collection in the young generation happens when the space in this generation fills up and is called the minor collection. Minor collections can be optimized assuming a high infant mortality rate.  It is well-tuned in the sense that the young generation is large enough (and thus the period between minor collections long enough) that the minor collection can take advantage of the high infant mortality rate. The time required for garbage collection is directly proportional to the number of live objects.  A young generation full of dead objects is collected very quickly. Some surviving objects are moved to a tenured generation.

The Tenured Generation

Objects which survive the young generation are eventually moved into the tenured generation. Garbage collection in the tenured generation happens when the space in the tenured generation fills up and is called the major collection. Since the tenured generation usually have a large number of alive objects, the time required for garbage collecting the tenured generation is much higher than that for the young generation. Hence, garbage collection of the tenured generation is done at a much lesser rate than the young generation.

The Permanent Generation

The permanent generation is not used for allocating objects. Instead it is used for holding the data needed by the virtual machine to describe objects that do not have equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation.


아래의 pdf파일은  Fillip Hanik이라는 개발자의 Inside the Java Virtual Machine: Memory Management and Troubleshooting이라는 제목의 슬라이드로 위의 내용을 이해하는데 도움이 된다.

출처:  http://www.springsource.com/files/uploads/all/pdf_files/news_event/Inside_the_JVM.pdf


  

  
HeadFirst Javascript 책에 보면 Youcube라는 가상의 블로그 서비스를 AJAX로 구현하였는데 거기에다가 아래의 기능을 추가

1. 디버깅 콘솔 추가
2. 5초에 한번씩 data파일이 변경되었는지 체크해서 변경되었으면 새로 읽어오고, 변경되지 않았으면 읽어오지 않음

자바스크립트 책 본지 이틀밖에 안된 초보이니 코드가 허접하더라도 양해해 주시길 바랍니다.

 
  

Java에서 중첩 루프 한번에 탈출 하는법

Posted by epicdev Archive : 2012. 1. 26. 22:22
중첩 루프를 돌면서 어떠한 조건이 만족하면 탈출하는식의 코드를 자주 코딩을 하게 된다.
이런 유형은 대개 아래와 같다.

일반적으로 이런 경우에는 아래와 같은 방법으로 코딩을 하게 된다.
혹은 중첩 루프를 함수로 만들어서 if 절 안의 break를 return으로 바꿔서 한번에 루프를 탈출하는 방법을 쓰기도 한다.
C++의 경우 goto를 사용하면 더 간단하게 이 문제를 해결할 수 있다.
물론 goto는 무조건 사용하지말라고 배웠다면 이러한 방법이 꺼려지겠지만,
거의 유일하게 goto를 써도 욕을 먹지 않는 경우가 바로 아래의 경우이다.
flag에 대한 설명을 주저리 주저리 할 필요도 없고, 코드의 가독성 또한 훨씬 높아진다.
하지만 Java에서는 goto문이 없다. 즉, C++에서처럼 goto를 사용해서 중첩 루프를 탈출 할 수 없다는 것이다.
하지만 Java에서는 이와 비슷한 다른 문법적 장치가 있다.
Java에서는 위와 같이 코딩을 하면 중첩 루프를 한번에 탈출할 수 있다.
왜 이런지 이해가 되지 않는다면 아래처럼 named block을 사용했다고 생각하면 된다.
혹은
  

Encapsulate Downcast (다운캐스트의 캡슐화)

Posted by epicdev Archive : 2012. 1. 25. 00:26
문제: 메소드의 리턴 값을 호출하는 쪽에서 다운캐스트하지 않으면 안 된다.

해법: 다운캐스트를 메소드 내부에서 하자.


  

Encapsulate Collection (컬렉션의 캡슐화)

Posted by epicdev Archive : 2012. 1. 25. 00:22
문제: 변경가능한 컬렉션을 반환하는 getter 메소드가 있기 때문에 외부에서 컬렉션을 직접 조작한다.


리팩토링입문
카테고리 컴퓨터/IT > 프로그래밍/언어
지은이 히로시 유키 (한빛미디어, 2007년)
상세보기


  
 «이전 1 ··· 3 4 5 6 7 8 9 ··· 17  다음»