<blockquote>
<p>5 GB log is parsed about 25 minutes</p>
</blockquote>
<p>在Python <a href="https://stackoverflow.com/q/9371238/4279">can do much better (~500MB/s for ^{<cd2>})</a>中,即使是顺序<code>O(n)</code>扫描,也就是说,性能只受i/O的限制</p>
<p>要对文件执行二进制搜索,您可以调整使用固定记录的<a href="https://stackoverflow.com/a/5219275/4279">FileSearcher</a>,使用类似于
<a href="https://stackoverflow.com/a/136368/4279">^{<cd3>} implementation in Python</a>(它是<code>O(n)</code>来扫描{<cd5>})。</p>
<p>为了避免<code>O(n)</code>(如果日期范围只选择了日志的一小部分),您可以使用一个近似的搜索,该搜索使用较大的固定块,并允许由于某些记录位于块边界上而丢失某些记录,例如,使用带<code>record_size=1MB</code>的未修改{<cd7>}和自定义的<code>Query</code>类:</p>
<pre><code>class Query(object):
def __init__(self, query):
self.query = query # e.g., '2012-01-01'
def __lt__(self, chunk):
# assume line starts with a date; find the start of line
i = chunk.find('\n')
# assert '\n' in chunk and len(chunk) > (len(self.query) + i)
# e.g., '2012-01-01' < '2012-03-01'
return self.query < chunk[i+1:i+1+len(self.query)]
</code></pre>
<p>考虑到日期范围可以跨越多个块,可以修改<code>FileSearcher.__getitem__</code>返回<code>(filepos, chunk)</code>,并搜索两次(<code>bisect_left()</code>,<code>bisect_right()</code>)以找到近似的<code>filepos_mindate</code>,<code>filepos_maxdate</code>。之后,您可以围绕给定的文件位置执行线性搜索(例如,使用<code>tail -n</code>方法)以找到确切的第一个和最后一个日志记录。</p>