[컴] python io 성능관련 글

 python bulk write / text write to file / 파일 write / file io 빠르게 /

python io 성능관련 글

Text I/O

text stream 을 만드는 간단한 방법은 open() 함수를 사용하는 것

f = open("mytext", "r")

in-memory text stream 들은 StringIO object들을 이용하면 된다.

f = io.StringIO("initial text")

Binary I/O

Binary I/O 를 buffered I/O 라고 도 부른다.

f = open("myfile.jpg", "rb")

in-memory binary stream

f = io.BytesIO(b"some initial binary data: \x00\x01")

성능

ref.1 에 좋은 글이 있어서 일부 번역을 해 놓는다.

다음 4가지에 IO에 대한 성능 이야기다.

  1. Binary I/O
  2. Text I/O
  3. Multi-threading
  4. Reentrancy

Binary I/O

buffered I/O 는 사용자가 1 byte를 요청해도, 많은 양의 데이터만 읽고 기록함으로써 os의 unbuffered I/O 루틴들을 불러서 수행할 때 생기는 비효율을 숨긴다. 이득(benefit)은 OS와 ’수행하는 I/O 종류’에 달려있다. 예를 들면, linux 같은 최신 OS들 에서는 unbuffered disk I/O 가 buffered I/O 보다 더 빠를 수 있다. 그러나 최소한(bottom line), buffered I/O 는 지원장치(backing device)나 플랫폼에 상관없이 예측가능한 성능을 제공한다는 것이다. 그런이유로 ’buffered I/O 를 사용하는 것’은 binary data 에 대해서 unbuffered I/O를 사용하는 것보다는 거의 언제나 선호된다.

Text I/O

file같은 binary storage(저장)에 대한 Text I/O 는 같은 저장에 대한 binary I/O 에 비해 현저히 늦다. 왜냐하면, Text I/O 는 unicode 와 binary data 사이에 문자 코덱을 이용한 변환이 필요하기 때문이다. 이것은 큰 log file들 같은 거대한 양의 text data에 대한 처리에서 눈에띄게 느릴 것이다. 또한 TextIOWrapper.tell()TextIOWrapper.seek() 의 경우는 사용되는 재구성 방법(reconstruction algorithm)때문에 둘다 꽤나 느리다.

그러나 StringIO는 native in-memory unicode container면서 BytesIO 와 유사한 속도를 보여줄 것이다.

Multi-threading

FileIO object들은 그들이 wrap 한 Unix 에서 read(2) 같은 os system call 들 thread-safe 하는 정도로 thread-safe 하다. (me: 그들이 wrap 한 함수만큼 thread-safe 하다는 말인듯.)

Binary buffered object들(BufferedReader,BufferedWriter,BufferedRandom,BufferedRWPair)은 그들의 내부 구조들을 lock 을 이용해서 보호한다. 그렇기 때문에 여러 thread 에서 동시에 그들을 호출하는것이 안전하다.

TextIOWrapper object들은 thread-safe 하지 않다.

Reentrancy

Binary buffered object들(BufferedReader,BufferedWriter,BufferedRandom,BufferedRWPair)은 reentrant 하지 않다. 반면에 reentrant call들은 일반적인 상황에서 일어나지 않지만, 그들은 signal handler 에서 I/O 를 하고 것으로부터 일어날 수 있다.

만약에 thread 가 이미 접근했던 buffered object 에 재진입(re-enter) 하려고 노력한다면, RuntimeError 가 발생된다. 하지만 이것은 다른 thread 가 buffered object 로 들어가는 것을 막지 않는다.

위의 이야기는 잠재적으로 text file들로 확장된다. open() 함수가 TextIOWrapper 내에서 buffered object 를 wrap 할 것이기 때문이다.

정리

명확하지 않지만, 지금 뇌피셜로 어느정도 flow 를 정리해보면, 아래와 같지 않을까 싶다. 일단 아래 사항은 그저 뇌피셜로 만든것이라 너무 믿지말자.

  write('fds') ---->  memory (os buffer) ----> device buffer ---> device
  write('fds') ---->  memory (ByteIO buffer) ----> memory (os buffer) ----> device buffer ---> device
  • text i/o 작업할때 좀 더 빠른 성능은 StringIO 를 이용하자.
  • 대체로 buffered I/O 가 빠르다.
  • binary buffered object 들은 thread-safe 하다

StringIO 내용을 file 로 wrtie 하기

shutil 를 이용해서 복사한다.

with open('file.xml', 'w') as fd:
  buf.seek(0)
  shutil.copyfileobj(buf, fd)

See Also

  1. 쿠…sal: [컴] java 에서 stream 과 reader/writer 의 차이

References

  1. io — Core tools for working with streams — Python 3.10.7 documentation

댓글 없음:

댓글 쓰기