मैं कुछ कोड लिख रहा हूं जो लॉग फाइलों को पार्स करता है, यह चेतावनी है कि इन फ़ाइलों को संकुचित किया गया है और फ्लाई पर असंपीड़ित होना चाहिए। यह कोड कोड का कुछ हद तक प्रदर्शन संवेदनशील टुकड़ा है, इसलिए मैं सही खोजने के लिए विभिन्न विधियों का प्रयास कर रहा हूं। मेरे पास अनिवार्य रूप से उतनी रैम है जितनी कार्यक्रम की आवश्यकता होगी, भले ही मैं कितने धागे का उपयोग कर रहा हूं।mmap बनाम malloc: अजीब प्रदर्शन
मुझे एक ऐसी विधि मिली है जो काफी अच्छी तरह से प्रदर्शन करती है, और मैं समझने की कोशिश कर रहा हूं कि यह बेहतर प्रदर्शन क्यों प्रदान करता है।
दोनों विधियों में एक पाठक धागा है, जो एक पाइप वाली जीजीआईपी प्रक्रिया से पढ़ता है और एक बड़े बफर को लिखता है। अगली लॉग लाइन का अनुरोध होने पर यह बफर तब आलसी ढंग से पार्स किया जाता है, जो अनिवार्य रूप से पॉइंटर्स की एक संरचना है जहां विभिन्न फ़ील्ड बफर में रहते हैं।
कोड डी में है, लेकिन यह सी या सी ++ के समान है।
साझा चर:
shared(bool) _stream_empty = false;;
shared(ulong) upper_bound = 0;
shared(ulong) curr_index = 0;
पार्स कोड:
//Lazily parse the buffer
void construct_next_elem() {
while(1) {
// Spin to stop us from getting ahead of the reader thread
buffer_empty = curr_index >= upper_bound -1 &&
_stream_empty;
if(curr_index >= upper_bound && !_stream_empty) {
continue;
}
// Parsing logic .....
}
}
विधि 1: Malloc एक बफर इतना बड़ा अप सामने अनज़िप फ़ाइल धारण करने के लिए।
char[] buffer; // Same as vector<char> in C++
buffer.length = buffer_length; // Same as vector reserve in C++ or malloc
विधि 2: उपयोग एक गुमनाम स्मृति नक्शा एक बफर के रूप
MmFile buffer;
buffer = new MmFile(null,
MmFile.Mode.readWrite, // PROT_READ || PROT_WRITE
buffer_length,
null); // MAP_ANON || MAP_PRIVATE
रीडर धागा:
ulong buffer_length = get_gzip_length(file_path);
pipe = pipeProcess(["gunzip", "-c", file_path],
Redirect.stdout);
stream = pipe.stdout();
static void stream_data() {
while(!l.stream.eof()) {
// Splice is a reference inside the buffer
char[] splice = buffer[upper_bound..upper_bound + READ_SIZE];
ulong read = stream.rawRead(splice).length;
upper_bound += read;
}
// Clean up
}
void start_stream() {
auto t = task!stream_data();
t.executeInNewThread();
construct_next_elem();
}
मैं विधि 1 से बाहर काफी बेहतर प्रदर्शन हो रही है, यहां तक कि पर परिमाण
User time (seconds): 112.22
System time (seconds): 38.56
Percent of CPU this job got: 151%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:39.40
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 3784992
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 5463
Voluntary context switches: 90707
Involuntary context switches: 2838
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
का क्रम
बनाम
User time (seconds): 275.92
System time (seconds): 73.92
Percent of CPU this job got: 117%
Elapsed (wall clock) time (h:mm:ss or m:ss): 4:58.73
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 3777336
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 944779
Voluntary context switches: 89305
Involuntary context switches: 9836
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
हो रही विधि 2. साथ जिस तरह से अधिक पेज दोष
किसी की मदद कर सके मुझे क्यों वहाँ प्रदर्शन में इस तरह के एक बुनियादी कमी mmap का उपयोग कर पर प्रकाश डाला?
यदि कोई समस्या को पूरा करने के किसी भी बेहतर तरीके से जानता है, तो मैं खुशी से इसे सुनूंगा।
संपादित करें -----
बदली गई विधि 2 करने के लिए:
char * buffer = cast(char*)mmap(cast(void*)null,
buffer_length,
PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE,
-1,
0);
अब एक सरल MmFile का उपयोग करने पर एक 3x प्रदर्शन वृद्धि हो रही है। मैं यह समझने की कोशिश कर रहा हूं कि प्रदर्शन में इतनी तेज भिन्नता क्या हो सकती है कि यह अनिवार्य रूप से केवल mmap के आसपास एक रैपर क्या है। सिर्फ एक सीधी चार * mmap बनाम Mmfile प्रयोग करने के लिए
Perf संख्या, जिस तरह से जिस तरह से कम पेज दोष:
User time (seconds): 109.99
System time (seconds): 36.11
Percent of CPU this job got: 151%
Elapsed (wall clock) time (h:mm:ss or m:ss): 1:36.20
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 3777896
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 2771
Voluntary context switches: 90827
Involuntary context switches: 2999
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
ठीक है, कुछ भी अप्रत्याशित नहीं है। 'mmap() 'फ़ाइल को स्कंक द्वारा' खंड में 'दोषपूर्ण' होने का कारण बनता है। I/O की मात्रा दोनों मामलों में समान है, लेकिन यह mmap() मामले में कम वांछनीय क्षणों पर किया जाता है। – wildplasser
और mmap opIndex (अधिभारित विधि) का उपयोग करता है, इसके बजाय आप 'buffer = mmap [];' –
वाइल्डप्लेसर करके सीधे पहुंच के लिए शून्य [] को खींच सकते हैं, मैं इसे एक्सेस करने से पहले सीधे पाइप से एमएमएपी पर लिख रहा हूं। तो मैं उन्हें लिखने से पहले लोड करने के लिए पेजों पर इंतजार कर रहा हूं बनाम उन्हें मॉलोक के साथ आगे बढ़ा रहा हूं? मैं उनसे पढ़ने से पहले एक पाइप से एमएमएपी को सीधे लिख रहा हूं, इसलिए मुझे लगता है कि उन पृष्ठों को थोड़ी देर के लिए कैश किया जाएगा। – sprw121