Study- MSC/Computer2008. 10. 21. 19:55
  C하면 포인터가 문제라고 한다. 사실 난 포인터를 배울 때 다른 부분에 비해 고생은 했지만 그렇다고 그렇게 힘들게 느끼진 않았다. 다만, 많이 헷갈렸던 부분은 바로 동적 할당이라는 부분이였다. 처음에 동적할당 자체를 공부하고 활용할때는 그리 어렵지 않았는데, 객체지향이라는 개념을 공부하기 시작하면서 혼란스러워지기 시작했다. 그동안 인식하고 있던 개념 자체가 흔들렸었던 것 같다.
  그 이후에 어느정도 안정(?)을 찾으면서 생각하길 이 동적할당과 관련된 부분을 이해하면 포인터도 큰 고비는 넘길 수 있겠고 객체의 사용에서도 많은 도움이 될 것이라고 생각했다.
  그래서 2~3개의 포스팅(또는 더 많이)을 통해서 이 동적 할당과 관련된 부분을 한번 이야기 해보자 한다.
  그 첫번째 포스팅으로, 메모리의 사용에 관한 간단한 이야기를 해보자 한다. 메모리, 간단히 '기억하는 공간'이다. 무엇을? 그 무엇이든. 예를 들어 정수 하나를 기억하는 공간을 만들고 싶다. 그러면 'int a'라고 a라는 정수형 변수를 만들면 된다. 다른 것 없다. 그리고 이 a라는 이름을 가진 공간은 '메모리 어딘가'에 sizeof(int)만큼 차지하고 있을 것이다. 
  이 '메모리 어딘가'를 어떻게 알까? 바로 메모리 주소로 알 수 있다. 그런데 이 메모리 주소를 우리가 일일히 기억하고 있어야 할까? 그럴 필요 없다. 다만 우리는 그 주소 대신 a라는 이름을 알고 있기 때문이다. a라는 별명의 주소에 있는 공간에 '4'라는 데이터를 넣고 싶다면 그냥 a = 4라고 해 주면 되고 읽고 싶으면 a라는 공간에서 꺼내 읽으면 된다.
  그리고 배열이라는 것이 있다.(배열에 관한 설명은 하지 않겠다.)이 배열은 메모리에 연속된 공간을 할당해서 데이터를 구조적으로 관리 할 수 있게 된다. 하지만 배열의 단점은 그 크기가 항상 고정되어 있다는 것이다. 학생의 성적을 관리 하는 프로그램을 만들기 위해 학생 수만큼 변수를 만들고 싶은데 그 수가 일정하지 않다면? 이런 방식에서는 배열은 좋은 방법이 아니다. 
  그럼 배열을 대체할 다른 메모리 사용 방식은 뭐가 있을까? 바로 동적 할당을 이용하는 것이다. 이 동적 할당에 관한 이야기는 다음 포스팅에서 포인터의 사용과 함께 같이 언급해 보겠다.
Posted by 머리
Study- MSC/Computer2008. 10. 1. 21:27
  예전에 비트맵을 분석해보려고 이것 저것 소스를 보다가 재밌는 코드를 본 적이 있다.
  비트맵을 파일 입출력으로 직접 읽어서 분석하는게 아니라 메모리를 할당한 후 파일에서 메모리로 전체를 복사시킨 후 파일은 닫고 메모리의 내용만 읽는 코드였다.
  흥미로운 방식이였다. 그러면서 든 생각이 그럼 바로 파일 입출력을 하는 것과 메모리에 올려서 하는 방식과 무엇이 다를까? 하는 것이였다. 그리고 이번 휴가를 통해서 바로 시험해 보았다.

실험 방법 : 어느정도 용량이 되는 TEXT 파일을 스트림에서 직접 읽는 방식과 메모리에 올려서 읽는 방식의 속도를 비교

소스 코드는 다음과 같다.


#include <stdio.h>
#include <stdio.h>
#include <windows.h>//GetTickTIme 호출

#define COUNT 1000000

//메모리를 통해서 파일을 읽는 것과 직접 FIle Stream에서 읽어 오는 것의 속도 비교

int main(void)
{

    FILE* fp;//파일을 읽을 파일 포인터
    char read[100];
    char a;
    char* str;

    unsigned int FileSize;
    int StreamTime;//스트림으로 읽었을 때의 시간
    int MemoryTime;//메모리로 했을 때의 시간

    //읽을 파일을 만드는 부분
    unsigned long i;

    if(fp = fopen("TestFile.txt","w"))
    {
        for(i = 0 ; i < COUNT ; i++)
        {
            fputs("TestFileText\n",fp);
        }

        fclose(fp);
    }


    //File Stream에서 읽기
    if(fp = fopen("TestFIle.txt","r"))
    {
        StreamTime = GetTickCount();  //시간 재기
        while(!feof(fp))
        {
            fgets(read,80,fp);
            printf("%s",read);
        };
        StreamTime = GetTickCount() - StreamTime;
        fclose(fp);
    }

    //Memory에 올린 후 읽기
    if(fp = fopen("TestFIle.txt","r"))
    {

        MemoryTime = GetTickCount();//재기 시작

        fseek(fp,0L,SEEK_END);
        FileSize = ftell(fp);//파일의 크기를 알기 위해 끝까지 이동 후 크기 저장

       
        str = malloc(sizeof(char) * FileSize);//크기 만큼 메모리 할당
        memset(str,0,FileSize);
        fseek(fp, 0L, SEEK_SET);//파일의 처음으로 이동
        fread(str,sizeof(char)*FileSize,1,fp);//파일을 메모리에 복사

        fclose(fp);//다 읽었으니 파일을 닫는다.

        printf("%s",str);//읽은 내용을 출력

        MemoryTime = GetTickCount() - MemoryTime;//측정 끝
        printf("소요 시간 : %d Tick\n",MemoryTime);

        free(str);//메모리 해제
    }

    printf("Stream : %d\nMemory : %d\n",StreamTime,MemoryTime);

    return 0;
}

실험 결과

내용 출력 하는 시간 포함해서 결과는

스트림 직접 읽기 : 45542 Tick
메모리 올려서 읽기 : 10656 Tick

약 23%정도 메모리로 읽는 방식이 더 빨랐다.
프린트 시간을 뺴서 계산 하면 더 정확한 결과를 얻을 수 있었을 것이다.

이번 실험으로 역시 메모리에 올려 놓고 돌리는 것이 속도 면에서는 더 효과적이라는 걸 직접 볼 수 있었다. 이런 것을 이용하면 Progress를 계산한다던가, 리소스 같은 것을 올려 놓고 읽으면 Loading TIme을 줄일 수 있을 것이다.
 
이렇게 메모리에 올리는 방식을 사용하는 예로 더블 버퍼링을 예로 들 수 있을 것이다. 더블 버퍼링도 메모리에 뿌릴 내용을 미리 그려 놓고 화면에 한꺼번에 뿌리는 방식을 이용한다.


그런데 의문점이 있어. 저렇게 하면 효과는 있지만 실제로 메모리에 대용량으로 할당하는 식으로는 잘 안할 거라고 생각해.
malloc()이런 걸로 몇 MB나 하는 걸 할당하는것도 무식하다고 생각하고 요즘 프로그램들 용량 엄청나잖아. 그런걸 보조하기 위해서 페이징같은 것이 있는거고

그래도 위 방법은 어느 정도 규모의 리소스 파일들을 읽을 때는 유용한 방법이 될 거라고 생각하는데, malloc같은 할당 함수 위에 다른 방법은 없는건지, 그리고 HEAP 영역 말고 이런 상황같은 것을 위한 다른 할당 가능 공간은 없는 건지 궁금하다. 한번 알아 봐야 겠다.


Posted by 머리