php Editor Apple Go 언어에서는 대용량 텍스트 파일을 처리해야 하는 경우가 많습니다. 때때로 우리는 특정 패턴을 포함하는 행에만 관심이 있고 다른 행은 무시합니다. 다행히 Go에서는 정규식과 bufio.Scanner를 사용하여 이 목표를 달성할 수 있습니다. 정규식을 사용하여 줄을 일치시키고 스캐너를 통해 파일을 한 줄씩 실행함으로써 관심 없는 줄을 쉽게 필터링할 수 있습니다. 이 팁은 효율성을 향상시킬 뿐만 아니라 코드를 더욱 간결하고 읽기 쉽게 만듭니다. 다음으로 Go에서 긴 텍스트 파일의 패턴이 포함된 줄을 무시하는 방법을 살펴보겠습니다.
go에서 긴 텍스트 파일(ascii 보장)에서 패턴이 포함된 줄을 무시하는 기능을 구현하려고 합니다
저는 withoutignore
和 withignore
下面的函数都接受文件名参数输入并返回 *byte.buffer
,随后可用于写入 io.writer
입니다.
withignore
函数采用附加参数 pattern
从文件中排除包含模式的行。该函数可以工作,但通过基准测试,发现它比 慢 5 倍而不忽略
. 개선할 수 있는 방법이 있나요?
벤치마크
으아악명령줄에서도 사용할 수 있습니다“base64dump.log”生成
package main import ( "bufio" "bytes" "io" "log" "os" ) func withoutignore(f string) (*bytes.buffer, error) { rfd, err := os.open(f) if err != nil { log.fatal(err) } defer func() { if err := rfd.close(); err != nil { log.fatal(err) } }() inputbuffer := make([]byte, 1048576) var bytesread int var bs []byte opbuffer := bytes.newbuffer(bs) for { bytesread, err = rfd.read(inputbuffer) if err == io.eof { return opbuffer, nil } if err != nil { return nil, nil } _, err = opbuffer.write(inputbuffer[:bytesread]) if err != nil { return nil, err } } return opbuffer, nil } func withignore(f, pattern string) (*bytes.buffer, error) { rfd, err := os.open(f) if err != nil { log.fatal(err) } defer func() { if err := rfd.close(); err != nil { log.fatal(err) } }() scanner := bufio.newscanner(rfd) var bs []byte buffer := bytes.newbuffer(bs) for scanner.scan() { if !bytes.contains(scanner.bytes(), []byte(pattern)) { _, err := buffer.writestring(scanner.text() + "\n") if err != nil { return nil, nil } } } return buffer, nil } func main() { // buff, err := withoutignore("base64dump.log") buff, err := withignore("base64dump.log", "audit") if err != nil { log.fatal(err) } _, err = buff.writeto(os.stdout) if err != nil { log.fatal(err) } }
ASCII가 보장되므로 byte
수준에서 직접 작동할 수 있습니다.
그러나 입력을 읽을 때 각 바이트에서 개행 문자를 확인한 다음 줄 내에서 패턴을 다시 검색하면 작업이 각 바이트에 적용됩니다.
반면, 각 입력 바이트를 확인하지 않고도 입력 블록을 읽고 텍스트의 패턴에 대한 최적화된 검색을 수행하면 입력 바이트당 작업을 최소화할 수 있습니다.
예를 들어 boyer-moore 문자열 검색 알고리즘입니다. Go에 내장된 bytes.index
기능도 최적화되었습니다. 물론 달성되는 속도는 입력 데이터와 실제 모드에 따라 달라집니다. 질문에 지정된 입력에 대해 측정 시 `bytes.index의 성능이 크게 향상되었습니다.
프로그램
bytes.index
블록에서 패턴이 발생하는 위치를 찾을 수 있습니다 참고할 만한
읽기 작업은 블록 크기보다 적은 데이터를 반환할 수 있으므로 데이터의 블록 크기를 읽을 때까지 읽기 작업을 반복하는 것이 좋습니다.
벤치마크
최적화된 코드는 일반적으로 훨씬 더 복잡하지만 나중에 살펴보겠지만 훨씬 더 나은 성능을 발휘합니다.
으아악여기서 최적화된 코드benchmarktestfilter-8
只比没有过滤的操作慢1.9倍左右,而benchmarktestwithignore-8
방법은 필터링되지 않은 비교 값보다 5.4배 느립니다.
다른 관점에서 살펴보세요. 최적화된 코드는 최적화되지 않은 코드보다 2.8배 빠릅니다.
코드
물론, 자체 테스트를 위한 코드는 다음과 같습니다.
으아악벤치마크 섹션은 다음과 같습니다.
으아악필터 기능이 분할되어 실제 작업은 func filter(reader io.reader,pattern []byte, chunksize int) (*bytes.buffer, error)
에서 이루어집니다.
여기에는 없지만 인덱스를 다룰 때 반드시 권장되는 리더 및 청크 크기를 주입하여 단위 테스트 생성을 준비하거나 고려했습니다.
그러나 여기서 중요한 점은 성능을 크게 향상시킬 수 있는 방법을 찾는 것입니다.
위 내용은 Go의 긴 텍스트 파일에서 패턴이 포함된 줄을 무시합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!