2016-06-10 1 views
1

저는 Jan Newmarch의 "Go with Network Programming"에서 공부했습니다. 거의 모든 그의 예제가 쓰기와 읽기 연결을위한 버퍼로 [512] 바이트를 포함한다는 것을 알았습니다.Go에서 읽기 및 쓰기를 위해 길이 512, 즉 [512] 바이트의 버퍼 바이트 배열이 필요한 이유는 무엇입니까?

온라인으로 검색하려했지만 답변을 얻지 못했습니다. 나는 그것이 i/o와 관련이 있을지도 모른다고 생각하지만이 설계의 정확한 이유가 무엇인지 확실하지 않습니다.

누구나 버퍼를 선택할 수 있습니까? 이 책에서

일부 샘플 코드 :

func handleConn(c net.Conn){ 
    defer c.Close() 

    var buf [512]byte 

    for{ 
     n, err := c.Read(buf[0:]) 

     if err != nil{ return } 

     _, err2 := c.Write(buf[0:]) 

     if err2 != nil{ 
      return 
     } 
    } 
} 
+0

편리한 크기입니다. 왜 당신은 500이라는 것 대신에 512를 의미합니까? – JimB

+0

그래, 그렇지만 256 대신 더 좋아? 또는 2의 힘과 비교적 큰 것. –

+1

좋은 스레드를 찾았습니다. http://stackoverflow.com/questions/236861/how-do-you-determine-the-ideal-buffer-size-when-using-fileinputstream – molivier

답변

1

아니 직접적인 대답하지만, 다른 사람들이 의견에 명시된 것 이외에 약간의 배경 지식이 필요합니다.

이동] 랩 파일, 소켓들이이 시스템을 통해 비동기 I/O를 사용할 때 더 까다로운, 시스템 콜에서 그 결과를 이루어 어떤 Read()Write() 호출이 소켓 (수행되는 점에서 상대적으로 얇은 유형 (예 : epoll, kqueue, IOCP 등). 즉, 파일이나 네트워크에서 1 바이트 덩어리로 읽는 것이 비효율적입니다.

또 다른 극단적 인 것을 고려하기 위해, 예를 들어 100MiB 버퍼를 할당하고 Read()으로 전달하려고 시도 할 수 있습니다. 커널의 시스템 호출이 그 크기의 대상을 기꺼이 받아 들일 것이지만, 현대 OS에는 네트워크 소켓에 내부 버퍼가 있고 약 128KiB의 크기로되어 있으므로 대부분의 상황에서 Read() 전화는 많은 양의 데이터를 읽거나 적게. 즉, 대부분의 버퍼 공간을 낭비하게됩니다.

또 다른 고려 사항이 있습니다. 응용 프로그램의 소켓에서 데이터를 읽는 패턴은 무엇입니까?

소켓에서 열려있는 파일로 데이터를 스트리밍 할 때 버퍼링에 신경 쓰지 않아도됩니다 (다른 사람이 "올바른"크기를 선택하기를 원합니다). 이 경우에는 io.Copy() (현재 (1.6)은 32KiB의 내부 버퍼를 사용함)을 사용하십시오.

반대로 TCP를 전송으로 사용하는 일부 애플리케이션 수준 프로토콜을 구문 분석하는 경우 종종 고정 된 크기의 청크로 데이터를 읽어야합니다. 이 경우 가장 좋은 패턴은 소켓 bufio.Reader —을 포장하여 위에서 설명한 "작은 읽기"문제를 해결 한 다음 io.ReadFull()을 사용하여 필요한 크기의 로컬 어레이/슬라이스로 데이터를 읽을 수 있습니다 (가능하면 재사용 가비지 컬렉터에 대한 부담을 줄이기 위해 배열과 슬라이스).

또 다른 경우는 SMTP 또는 HTTP과 같은 텍스트 기반 "줄무늬"프로토콜입니다. 이 프로토콜에서 최대 라인 길이는 일반적으로 고정되어 있으며이를 처리하기 위해 프로토콜 라인의 최대 크기 버퍼를 사용하는 것이 좋습니다. (어쨌든, 그것은 net/textproto 표준 패키지를 사용하는 것이 가장 좋습니다, 같은 프로토콜을 처리 할 수 ​​있습니다.) 질문에 관해서는

자체는 그것에 내 찔린 512은 특별한 의미가없는 단지 아름다운 수 있다는 것이다 . 이 책을 쓸 때 값을 선택해야합니다.

네트워크에서 읽는 실제 작업 패턴에 대한 나의 설명에서 알 수 있듯이 대부분의 경우 버퍼링을 다루는 업무가 전혀 없습니다. — 표준 도구로이 작업을 수행 할 수 있습니다. 표준 패키지가 제공하는 기본값에 대한 실제 문제에 직면했을 때 그 점을 조정하는 것에 대해서만 생각해야합니다.

TL; DR

  • 당신이 단순히 읽고있는이 책은 당신에게 기본 개념을 설명하고, 그래서 어떤 번호를 사용한다.
  • 실제 코드는 버퍼링이 필요할 때 (보통 더 높음) & hellip;
  • & hellip;하지만 꼭 필요한 경우가 아니면 다음 번호에 신경 쓰지 마세요. 가능하면 기성 도구를 사용하십시오. 물론

1, 나는 모든 운영 체제에 대해 말할 수 없다, 그들은이 물건을 조정할 다른 손잡이가 있고, "현대"년 이상에 다른 의미를 시작할 수도 있고 덜, 당신은 & hellip 알고; 여전히 나는 나의 평가를 진리에 아주 가깝다고 생각한다.

+0

go에서 바이트 패키지에는 512로 설정된 MinRead라는 상수가 있으므로 일부 의미가있는 것처럼 보입니다. https://golang.org/pkg/bytes/?m=all#pkg-constants –

+0

@SethPollack, IMO는 빨간 청어입니다. 설명에서 상수는 버퍼의 조기 성장을 막는 데 사용되는 휴리스틱을 제공하는 것으로 보입니다. ReadFrom()'은 데이터를 읽습니다. 여러분은 결국 ... 511이나 516과 반대로 512에 관한 유일한 "마술"은 2^9라는 것입니다. 512 정확히 정확히 킬로바이트 (정확히는 kibibyte), 또는 두 번 2x128, 이는 2x122, 즉 2x32, 이는 2x16입니다 2x8입니다 .-) – kostix

+0

@SethPollack, 제 말은 , 보통 어셈블리 언어와 기계 코드를 배우는 것을 의미했던 당시에 프로그래밍을 시작하기 시작한 사람들을 위해, 512는 따뜻한 아늑한 느낌을 가지고 있습니다. ;-) 그것은 그러한 숫자가 사용되는 이유 중 일부입니다. 좀 더 진지한 고려 사항은 - 일부 아키텍처에서는 메모리 액세스가 주어진 크기의 메모리 블록의 시작 주소가 자연스럽게 정렬 될 때만 (또는 심지어 가능합니다!) 효과적이라는 것입니다. 말하자면 64 비트 단어를 읽으려면 8로 나누어 쓸 수있는 주소에 위치해야합니다. – kostix

관련 문제