이것은 제가 현재 진행하고있는 연구 프로젝트 중 하나입니다. 요구 사항은 거의 귀하의 요구 사항이며 문제를 해결하기 위해 멋진 알고리즘을 개발했습니다.
입력
입력은 끝없는 영어 단어 또는 구문 스트림입니다 (우리는이를라고 함 tokens
).
출력
- 지금까지 본 토큰 중 상위 N 개를 출력합니다 (우리가 본 모든 토큰에서!)
- 지난 날 또는 지난주와 같이 기록 창에서 상위 N 개 토큰을 출력합니다.
이 연구의 응용은 트위터 나 페이스 북에서 화제가되는 주제 나 주제의 트렌드를 찾는 것입니다. 웹 사이트를 크롤링하는 크롤러가있어 시스템에 입력되는 단어 스트림을 생성합니다. 그러면 시스템은 전체적으로 또는 역사적으로 최고 빈도의 단어 또는 구문을 출력합니다. 지난 몇 주 동안 "월드컵"이라는 문구가 트위터에 여러 번 나타날 것이라고 상상해보십시오. "Paul the octopus"도 마찬가지입니다. :)
정수로 문자열
시스템에는 각 단어에 대한 정수 ID가 있습니다. 인터넷에는 거의 무한한 단어가 있지만 많은 단어가 쌓이면 새로운 단어를 찾을 가능성이 점점 낮아집니다. 이미 4 백만 개의 서로 다른 단어를 찾았고 각각에 대해 고유 한 ID를 할당했습니다. 이 전체 데이터 세트는 해시 테이블로 메모리에로드 될 수 있으며 대략 300MB 메모리를 사용합니다. (우리는 자체 해시 테이블을 구현했습니다. Java의 구현에는 엄청난 메모리 오버 헤드가 필요합니다.)
그러면 각 구문을 정수 배열로 식별 할 수 있습니다.
정수에 대한 정렬 및 비교가 문자열보다 훨씬 빠르기 때문에 이것은 중요 합니다.
데이터 보관
시스템은 모든 토큰에 대한 아카이브 데이터를 유지합니다. 기본적으로 (Token, Frequency)
. 그러나 데이터를 저장하는 테이블이 너무 커서 테이블을 물리적으로 분할해야합니다. 일단 파티션 구성표는 토큰의 ngram을 기반으로합니다. 토큰이 한 단어이면 1 그램입니다. 토큰이 두 단어 구문 인 경우 2 그램입니다. 그리고 이것은 계속됩니다. 대략 4 그램에 10 억 개의 레코드가 있으며 테이블 크기는 약 60GB입니다.
들어오는 스트림 처리
시스템은 메모리가 완전히 활용 될 때까지 들어오는 문장을 흡수합니다 (예, MemoryManager가 필요합니다). N 개의 문장을 가져와 메모리에 저장 한 후 시스템은 일시 중지하고 각 문장을 단어와 구문으로 토큰 화하기 시작합니다. 각 토큰 (단어 또는 구)이 계산됩니다.
매우 빈번한 토큰의 경우 항상 메모리에 보관됩니다. 빈도가 낮은 토큰의 경우 ID를 기준으로 정렬되고 (문자열을 정수 배열로 변환하는 것을 기억하십시오) 디스크 파일로 직렬화됩니다.
(그러나 문제에 대해서는 단어 만 계산하므로 모든 단어 빈도 맵을 메모리에만 저장할 수 있습니다. 신중하게 설계된 데이터 구조는 400 만 개의 다른 단어에 대해 300MB 메모리 만 사용합니다. 일부 힌트 : ASCII 문자를 사용하여 문자열을 나타냄), 이것은 매우 수용 가능합니다.
한편, 시스템에서 생성 된 디스크 파일을 찾은 다음 병합을 시작하면 활성화되는 다른 프로세스가 있습니다. 디스크 파일이 정렬되어 있으므로 병합은 병합 정렬과 같은 유사한 프로세스를 수행합니다. 임의의 디스크 탐색을 너무 많이 피하고 싶기 때문에 여기에서도 일부 디자인을주의해야합니다. 아이디어는 읽기 (병합 프로세스) / 쓰기 (시스템 출력)를 동시에 피하고 병합 프로세스가 다른 디스크에 쓰는 동안 하나의 디스크에서 읽도록하는 것입니다. 이것은 잠금을 구현하는 것과 유사합니다.
하루의 끝
하루가 끝나면 시스템에는 빈도가 메모리에 저장되는 빈도가 높은 토큰이 많이 있고 여러 디스크 파일에 저장되는 빈도가 낮은 토큰이 많이 있습니다 (각 파일이 정렬 됨).
시스템은 메모리 내 맵을 디스크 파일로 플러시합니다 (정렬). 이제 문제는 정렬 된 디스크 파일 집합을 병합하는 것입니다. 유사한 프로세스를 사용하여 마지막에 정렬 된 디스크 파일 하나를 얻습니다.
그런 다음 마지막 작업은 정렬 된 디스크 파일을 아카이브 데이터베이스에 병합하는 것입니다. 아카이브 데이터베이스의 크기에 따라 알고리즘이 충분히 크면 아래와 같이 작동합니다.
for each record in sorted disk file
update archive database by increasing frequency
if rowcount == 0 then put the record into a list
end for
for each record in the list of having rowcount == 0
insert into archive database
end for
직감적으로 언젠가는 삽입 횟수가 점점 줄어들 것입니다. 점점 더 많은 작업이 업데이트에만 있습니다. 그리고이 업데이트는 인덱스에 의해 불이익을받지 않습니다.
이 전체 설명이 도움이되기를 바랍니다. :)
what is the most frequent item in the subsequence [2; 2; 3; 3; 3; 4; 4; 4; 4; 5; 5] of your sequence?