[英]Reading and graphing data read from huge files
我們有相當大的文件,將1-1.5 GB的數量級(主要是日志文件)與可輕松解析為csv的原始數據相結合,隨后應將其圖形化以生成一組圖形圖像。
當前,我們正在使用bash腳本將原始數據轉換為一個csv文件,其中僅包含需要繪制圖形的數字,然后將其輸入到gnuplot腳本中。 但是這個過程非常緩慢。 我試圖通過用單個awk
命令替換一些管道cut
s, tr
等來加快bash腳本的速度,盡管這提高了速度,但整個過程仍然很慢。
因此,我開始相信有用於此過程的更好的工具。 我目前正在尋找用python + numpy或R重寫此過程。我的一個朋友建議使用JVM,如果要這樣做,我將使用clojure,但不確定JVM的性能如何。
我在處理此類問題方面經驗不足,因此,任何有關如何進行的建議都將是很棒的。 謝謝。
編輯:此外,我將要存儲(到磁盤)生成的中間數據,即csv,因此,如果我選擇想要其他外觀的圖,則不必重新生成它。
編輯2:原始數據文件每行只有一條記錄,其字段由定界符( |
)分隔。 並非所有字段都是數字。 我在輸出csv中需要的每個字段都是通過在輸入記錄上應用特定公式獲得的,該公式可以使用輸入數據中的多個字段。 輸出的csv每行將有3-4個字段,我需要在(可能是)條形圖中繪制1-2、1-3、1-4字段的圖形。 我希望可以提供更好的畫面。
編輯3:我對@adirau的腳本進行了一些修改,它似乎運行得很好。 我已經走了足夠遠的距離,可以讀取數據,發送到處理器線程池(偽處理,將線程名稱附加到數據),並通過另一個收集器線程將其聚合到輸出文件中。
PS:我不確定這個問題的標簽,可以隨時改正。
python聽起來是個不錯的選擇,因為它具有良好的線程API(盡管實現存在疑問),matplotlib和pylab。 我從您的末端想起了更多的規格,但這也許對您來說是一個很好的起點: matplotlib:使用線程異步繪圖 。 我會選擇一個線程來處理大容量磁盤I / O讀取,並將隊列同步到線程池中進行數據處理(如果您具有固定的記錄長度,則可以通過預先計算讀取偏移量並將偏移量僅傳遞給線程池來加快處理速度) ; 使用diskio線程,我將映射數據源文件,讀取預定義的num字節+再讀取一次,以最終將最后一個字節捕獲到當前數據源lineinput的末尾; 應選擇接近平均行輸入長度的位置的字節數; 接下來是通過隊列進行池填充,以及在線程池中進行的數據處理/繪圖; 我在這里的情況不佳(確切地說明了您的繪圖),但我希望這會有所幫助。
編輯:有file.readlines([sizehint])一次抓住多行; 好吧,它可能不是那么快,因為文檔說它在內部使用readline()
編輯:快速骨架代碼
import threading
from collections import deque
import sys
import mmap
class processor(Thread):
"""
processor gets a batch of data at time from the diskio thread
"""
def __init__(self,q):
Thread.__init__(self,name="plotter")
self._queue = q
def run(self):
#get batched data
while True:
#we wait for a batch
dataloop = self.feed(self._queue.get())
try:
while True:
self.plot(dataloop.next())
except StopIteration:
pass
#sanitizer exceptions following, maybe
def parseline(self,line):
""" return a data struct ready for plotting """
raise NotImplementedError
def feed(self,databuf):
#we yield one-at-time datastruct ready-to-go for plotting
for line in databuf:
yield self.parseline(line)
def plot(self,data):
"""integrate
https://www.esclab.tw/wiki/index.php/Matplotlib#Asynchronous_plotting_with_threads
maybe
"""
class sharedq(object):
"""i dont recall where i got this implementation from
you may write a better one"""
def __init__(self,maxsize=8192):
self.queue = deque()
self.barrier = threading.RLock()
self.read_c = threading.Condition(self.barrier)
self.write_c = threading.Condition(self.barrier)
self.msz = maxsize
def put(self,item):
self.barrier.acquire()
while len(self.queue) >= self.msz:
self.write_c.wait()
self.queue.append(item)
self.read_c.notify()
self.barrier.release()
def get(self):
self.barrier.acquire()
while not self.queue:
self.read_c.wait()
item = self.queue.popleft()
self.write_c.notify()
self.barrier.release()
return item
q = sharedq()
#sizehint for readine lines
numbytes=1024
for i in xrange(8):
p = processor(q)
p.start()
for fn in sys.argv[1:]
with open(fn, "r+b") as f:
#you may want a better sizehint here
map = mmap.mmap(f.fileno(), 0)
#insert a loop here, i forgot
q.put(map.readlines(numbytes))
#some cleanup code may be desirable
我認為python + Numpy在速度和易於實現方面將是最有效的方法。 Numpy經過高度優化,因此性能不錯,而python將簡化算法實現部分。
該組合應該可以很好地適合您的情況,可以優化內存中文件的加載,並嘗試找到處理數據塊之間的中間點,該數據塊不是太大,但足夠大以最大程度地減少讀寫周期,因為是什么會減慢程序
如果您認為這需要進一步提高速度(我對此表示懷疑),則可以使用Cython來加快緩慢的零件的速度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.