♧강의목록1♧/중독-인터넷.스마트폰.게임

1000 GB는 1TB (테라바이트)...

花受紛-동아줄 2009. 1. 22. 22:51

1000 GB는 1TB (테라바이트)...

 

이렇게 큰 무시무시한 파일이 있을까요?

 

 테라바이트

 

 

 트랙백 주소 : http://www.tipssoft.com/bulletin/tb.php/FAQ/218 function clipboard_trackback(str) { if (g4_is_gecko) prompt("이 글의 고유주소입니다. Ctrl+C를 눌러 복사하세요.", str); else if (g4_is_ie) { window.clipboardData.setData("Text", str); alert!("트랙백 주소가 복사되었습니다.\n\nhttp://www.tipssoft.com/bulletin/tb.php/FAQ/218"); } }
* 이 자료를 퍼 가셔서 타사이트나 블로그에 게재 시 출처를 명시해 주시기 바랍니다.
  본 사이트에 게재된 모든 내용 및 자료는 상업적인 용도로 이용할 수 없습니다.
 
이 자료들은 저희 사이트에서 제공하는 [ 알짜배기 ] 프로그램을 이용하시면 좀더 편리하게 볼수 있습니다.
알짜배기 프로그램 받기 :  http://www.tipssoft.com/bulletin/tb.php/QnA/8406
 
 
GetDiskFreeSpace 함수를 이용하여 디스크의 전체 공간 과 남은 공간에 대한 정보를 얻을 수 있습니다.
이 함수의 원형은 아래와 같습니다.
 
BOOL GetDiskFreeSpace(
    LPCTSTR lpRootPathName,              // 정보를 얻을 디스크의 루트 경로명
    LPDWORD lpSectorsPerCluster,         // 하나의 클라스터를 구성하는 섹터의 수
    LPDWORD lpBytesPerSector,             // 섹터 하나의 크기 (byte) 
    LPDWORD lpNumberOfFreeClusters,  // 남은 클라스터의 수
    LPDWORD lpTotalNumberOfClusters  // 전체 클라스터의 수
);

GetDiskFreeSpace 함수를 사용하여 C 드라이브의 전체 디스크 공간과 여유 디스크 공간을 얻는
코드를 작성해보면 아래와 같습니다.
 
DWORD sectors_per_cluster = 0, bytes_per_sector = 0;
DWORD number_of_freeclusters = 0, totalnumber_of_clusters = 0;

// C 디스크 드라이브의 공간 정보를 얻는다.
GetDiskFreeSpace("C:\\", §ors_per_cluster, &bytes_per_sector,
                                                             &number_of_freeclusters, &totalnumber_of_clusters);
 
// 전체 디스크 공간을 GB단위로 연산한다.
double disk_size = sectors_per_cluster*bytes_per_sector*totalnumber_of_clusters;
disk_size = disk_size /1024/1024/1024;
 
// 남은 디스크 공간을 GB단위로 연산한다.
double disk_free_size = sectors_per_cluster*bytes_per_sector*number_of_freeclusters;
disk_free_size = disk_free_size /1024/1024/1024;
 
CString str;
str.Format("디스크 전체 공간 : %.2fGB / 남은 디스크 공간 : %.2fGB", disk_size, disk_free_size);
AfxMessageBox(str);

 

 

위키백과 ― 우리 모두의 백과사전.

기호(이름) 기호 기호(이름) V값
kB (킬로바이트) 10001 = 103 KB 10241 = 210 KiB (키비바이트) 210
MB (메가바이트) 10002 = 106 MB 10242 = 220 MiB (메비바이트) 220
GB (기가바이트) 10003 = 109 GB 10243 = 230 GiB (기비바이트) 230
TB (테라바이트) 10004 = 1012 TB 10244 = 240 TiB (테비바이트) 240
PB (페타바이트) 10005 = 1015 PB 10245 = 250 PiB (페비바이트) 250
EB (엑사바이트) 10006 = 1018 EB 10246 = 260 EiB (엑스비바이트) 260
ZB (제타바이트) 10007 = 1021 ZB 10247 = 270 ZiB (제비바이트) 270
YB (요타바이트) 10008 = 1024 YB 10248 = 280 YiB (요비바이트) 280

 

 

 

파이썬의 문자열 관련 연산은 직관적이고 편리하다. 기계보다는 인간에 가까운 고수준(high-level) 언어로서, 문자열 더하기, 문자열 슬라이스(slice) 등 편리한 기능이 많다.

그러나 몇 메가, 또는 몇 백메가에 해당하는 문자열을 더하고 수정하는데에는 적합하지 않다.

다음 예를 각자의 파이썬 인터프리터에서 실행해 보자. 전형적인 문자열 축적(?) 연산이다.


#
# Simple String Concatenation No.1
#
import! time
s = '$' * 1024
t = ''
s_time = time.time()
for i in xrange(1000):
	t = t + s
e_time = time.time()
print 'Elapsed Time:', (e_time - s_time)

예제 내용은 매우 간단하다. 변수 t 에 문자열 '$$$...$'(총 길이 1024)을 1000 번 더하여 총 길이 1024000 바이트인 문자열을 저장한다. 그리고 소요 시간을 계산하여 출력한다.

필자의 펜티엄 III 450 MHz 메모리 512 MB 리눅스 시스템에서 실행해 본 결과, 약 4.5 초 정도의 시간이 걸렸다.

파이썬에 있어 문자열 객체는 자체 변경불가능한(immutable) 객체이므로 문자열 + 문자열의 결과는 여러분이 기대한 것처럼 메모리 상에 존재하는 문자열 2 개가 연결되는 것이 아니라, 두 문자열을 합한 새로운 복사본을 탄생시킨다.

t = t + s는 t 문자열 복사본과 s 문자열 복사본을 합한 문자열을 만들고 그 문자열을 다시 t 에 할당한다. 이 때 t 의 기존 내용은 해제되고 새로운 문자열이 할당된다.

정리하면, 다음과 같다:


  1. t + s 를 보고 두 문자열이 들어갈 수 있을 만큼의 메모리 공간을 확보한다.

  2. t 문자열 내용과 s 문자열 내용을 그 메모리 공간에 복사한다.

  3. 이제 그 메모리 공간을 t 에 대입할 차례이다.

  4. t 가 원래 가리키고 있던 문자열 메모리 공간을 해제한다.

  5. 새로운 메모리 공간을 t 가 가리키도록 한다.

C 언어처럼 뭔가를 저장하기 위해서는 메모리 할당(malloc)과 메모리 해제(free)를 해 주어야 하는 언어를 사용해 본 사람은 저 단순하게 보이는 과정이 사실은 엄청난 malloc-free의 반복임을 이해할 수 있을 것이다.

앞서 1000 번 문자열 더하기 연산했던 것을 10000 번, 100000 번 정도 해 보라. 정말로 어마어마한 시간이 걸릴 것이다. 필자의 시스템에서 10000 번 연산은 478 초 걸렸다. 100000 번은 도저히 인내심을 가지고 지켜볼 수 없었다.

그 이유는 문자열 축적이 진행될 수록 할당해야 하는 메모리 크기가 커지고 동시에 해제해야 하는 메모리 크기도 커지기 때문이다. 시간이 날 때 100000 번 정도 루프를 돌게 하면서 시스템의 메모리가 어떻게 늘었다 줄었다 하는지 확인해 보라. 메모리가 충분하지 않은 시스템에서는 결국 MemoryError 예외를 먹고 프로그램이 죽을 것이다.

이와 같은 문자열 축적 연산은 매우 흔하다. 예를 들어, 생명공학도라면 DNA 염기서열을 분석하고 그 데이터를 계속해서 똑같은 변수에 축적하는 식의 프로그램을 많이 짜게 된다. 그리고 데이터가 방대해 질수록, 시간이 지날수록 프로그램이 종료할 생각을 안한다는 사실에 놀랄 것이다. 정말 C 언어로 해야 하는 것인가?

해결 방법?

필자를 이 문제를 위해 C 모듈을 특수하게 만들어 볼까 생각했다. 그러나, 이미 이 문제에 대한 해결책 또는 해결책을 만드는데 도움이 되는 모듈이 있을 것이라고 생각하고 파이썬 표준 모듈들을 검색해 보았다. 그 결과 찾은 것이 바로 cStringIO였다. (100% 만족하는 것은 아니지만)

cStringIO는 문자열을 추가할 때 메모리 크기 변경 할당 함수인 realloc을 사용하고 있다.

하지만 cStringIO 사용법은 다음과 같이 문자열 사용법과 판이하게 다르다:


#
# Simple String Concatenation No.2
#
from cStringIO import! StringIO
import! time
s = '$' * 1024
t = StringIO()
s_time = time.time()
for i in xrange(1000):
	t.write(s)
e_time = time.time()
print 'Elapsed Time:', (e_time - s_time)
#
# t.seek(0, 0)
# T = t.read()
#

이 방법으로 문자열 더하기를 실행해 보면, 필자의 시스템에서 0.012 초 정도 걸렸다. 4.5 초와 0.012 초의 차이를 보라.

StringIO 객체로부터 실제 문자열을 구하려면, getvalue() 메써드를 호출하여 문자열을 반환받으면 된다.

별로 파이썬답지 않다!

cStringIO 모듈을 사용했을 때, 파이썬의 기본 문자열 객체를 사용하는 것보다 놀라울 정도로 빠른 결과를 보여 주었지만, t = t + s 라는 표현과 t.write(s) 라는 표현을 놓고 보았을 때, 인간에게는 전자가 명료하게 보인다.

그리고 이미 작성한 코드가 있다면, 모두 전혀 다른(또한 어색해 보이는) 형식으로 변경해야 하는 수고를 해 주어야 한다.

필자의 목표는 최대한 "마치 보통의 문자열"처럼 사용할 수 있도록 도움을 주는 모듈을 만드는 것이었고, 그 결과물이 muString 모듈이다.

muString 모듈은 cStringIO 모듈을 사용하면서도 최대한 파이썬 문자열 객체처럼 사용할 수 있도록 포장한 모듈이다. 이 모듈을 사용하면 다음과 같이 코드를 작성할 수 있다:


#
# Simple String Concatenation No.3
#
from muString import! muString
import! time
s = '$' * 1024
t = muString()
s_time = time.time()
for i in xrange(1000):
	t += s
e_time = time.time()
print 'Elapsed Time:', (e_time - s_time)

muString 모듈 소스 코드는 [자료 링크]에서 볼 수 있다. 실행 시간은 0.05 초였다. cStringIO만 사용할 때보다는 오래 걸렸지만, 기본 파이썬 문자열 객체를 사용할 때보다는 여전히 빠른 결과를 보여준다.

t = muString() 이라고 적은 부분만 약간 생소하게 느껴질 것이다. 그러면서도 t += s 처럼 마치 문자열을 쓰는 것처럼 자연스럽게 표현한다.

(t = t + s 와 t += s가 같다고 생각할 지 모르지만 파이썬에서 이 둘은 전혀 다르게 구현되어 있으며 += 가 효율적이다. 만약 t += s 를 t = t + s로 바꾸면 오히려 기본 파이썬 문자열 객체를 사용하는 것보다 악화된다!)

10000 번 연산 시간은 0.6 초, 100000 번 연산 시간은 6 초 걸렸다.

시간 단축 효과를 생각할 때 데이터 수집 역할을 하는 변수 t 에 대한 변경을 가하고 t += s 라는 스타일을 사용하는 수고는 부담스럽지 않을 것이다.

더 큰 가치!

그 밖에도 다음과 같은 것이 가능하기 때문에 때에 따라 정말 유용하게 사용할 수 있다고 생각한다:

  • 첨자 연산 s[i], 슬라이스 연산 s[m:n] 지원

    s[0]

  • 반복 연산인 s *= n 지원

    s *= 2

  • 변경가능한(mutable) 문자열 객체처럼(!) 사용할 수 있다:

    s = muString('see')
    s[2] = 'a'
    print s

  • 길이가 동일하다면 슬라이스(slice) 치환도 가능하다:

    s = muString('see')
    s[0:3] = 'sea'
    print s

최대한 보통의 문자열 객체처럼 행동하면서도 자체 변경가능한 재미있는 속성을 가진 변종 문자열 객체(mutant string object)의 탄생이다.

자료 링크

muString 모듈은 표준 메써드를 오버라이드(override)하여 어떻게 표준적인 파이썬 객체처럼 동작하는 객체를 설계해서 사용할 수 있는가를 보여주기 위한 예제이다. 참고한 모듈은 UserString 모듈이다.

다운로드받아서 muString.py 라는 이름으로 변경해서 사용한다.

 

http://dns.paran.com/search/index.php?tab=search&Query=1024