2012-07-06 16 views
5

में पृष्ठों की पहचान करना मैं जानना चाहता हूं कि एक विशाल फ़ाइल का कौन सा हिस्सा स्मृति में कैश किया गया है। मैं इसके लिए fincore से कुछ कोड का उपयोग कर रहा हूं, जो इस तरह से काम करता है: फ़ाइल mmaped है, फिर पता स्थान पर फिनकोर loops और mincore के साथ पृष्ठों की जांच, लेकिन फ़ाइल आकार (कई टीबी) के कारण यह बहुत लंबा (कई मिनट) है)।लिनक्स: मेमोरी

क्या इसके बजाय प्रयुक्त RAM पृष्ठों पर लूप करने का कोई तरीका है? यह बहुत तेज़ होगा, लेकिन इसका मतलब है कि मुझे कहीं से भी इस्तेमाल किए गए पृष्ठों की सूची मिलनी चाहिए ... हालांकि मुझे एक सुविधाजनक सिस्टम कॉल नहीं मिल रहा है जो इसकी अनुमति देगा।

#include <errno.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <unistd.h> 
/* } */ 

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <sys/mman.h> 
#include <sys/sysinfo.h> 


void 
fincore(char *filename) { 
    int fd; 
    struct stat st; 

    struct sysinfo info; 
    if (sysinfo(& info)) { 
    perror("sysinfo"); 
    return; 
    } 

    void *pa = (char *)0; 
    char *vec = (char *)0; 
    size_t pageSize = getpagesize(); 
    register size_t pageIndex; 

    fd = open(filename, 0); 
    if (0 > fd) { 
     perror("open"); 
     return; 
    } 

    if (0 != fstat(fd, &st)) { 
     perror("fstat"); 
     close(fd); 
     return; 
    } 

    pa = mmap((void *)0, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); 
    if (MAP_FAILED == pa) { 
     perror("mmap"); 
     close(fd); 
     return; 
    } 

    /* vec = calloc(1, 1+st.st_size/pageSize); */ 
    /* 2.2 sec for 8 TB */ 
    vec = calloc(1, (st.st_size+pageSize-1)/pageSize); 
    if ((void *)0 == vec) { 
     perror("calloc"); 
     close(fd); 
     return; 
    } 

    /* 48 sec for 8 TB */ 
    if (0 != mincore(pa, st.st_size, vec)) { 
     fprintf(stderr, "mincore(%p, %lu, %p): %s\n", 
       pa, (unsigned long)st.st_size, vec, strerror(errno)); 
     free(vec); 
     close(fd); 
     return; 
    } 

    /* handle the results */ 
    /* 2m45s for 8 TB */ 
    for (pageIndex = 0; pageIndex <= st.st_size/pageSize; pageIndex++) { 
     if (vec[pageIndex]&1) { 
     printf("%zd\n", pageIndex); 
     } 
    } 

    free(vec); 
    vec = (char *)0; 

    munmap(pa, st.st_size); 
    close(fd); 

    return; 
} 

int main(int argc, char *argv[]) { 
    fincore(argv[1]); 

    return 0; 
} 
+2

एक 8 टीबी फ़ाइल मैपिंग के लिए 2 अरब 4k पृष्ठों की आवश्यकता है। 'मिनीकोर' के 48 सेकंड रनटाइम का मतलब है 44.7 मैपेज/सेकंड की जांच की जा रही है। आप कितनी तेज़ी से सोच सकते हैं कि यह जा सकता है? 'Printf()' के साथ लाखों या अरबों लाइनों को प्रिंट करना दुनिया में सबसे तेज़ चीज नहीं है। –

+0

मुझे उम्मीद है कि एमएमएपी/मिनीकोर उस से तेज नहीं होगा; मैं क्या चाहता हूं कि लूप लंबाई को कम करना संभवतः कम पृष्ठों को स्कैन करके ... – wazoox

+0

'printf' आमतौर पर बहुत धीमी गति से ऑपरेशन होता है।इसे 'activePages ++' जैसे कुछ के साथ बदलें और देखें कि लूप को संसाधित करने में कितना समय लगता है। ध्यान दें कि 'vec' अभी भी 2 जीबीबी है और यहां तक ​​कि' मिनीकोर 'को कॉल करना भी कैश की सामग्री को बदल सकता है क्योंकि 'vec' को आवंटित वर्चुअल एड्रेस स्पेस के अंदर भौतिक स्मृति को छुआ जा रहा है। –

उत्तर

0

किसके द्वारा संचित:

यहाँ कोड आता है?

बूट के बाद फ़ाइल डिस्क पर बैठती है। इसका कोई हिस्सा स्मृति में नहीं है।

अब फ़ाइल खोला गया है और यादृच्छिक पढ़ा जाता है।

फ़ाइल सिस्टम (उदा। कर्नेल) कैशिंग होगा।

सी मानक पुस्तकालय कैशिंग होगा।

कर्नेल कर्नेल-मोड मेमोरी, सी-मानक लाइब्रेरी में उपयोगकर्ता-मोड मेमोरी में कैशिंग होगा।

यदि आप कोई प्रश्न जारी कर सकते हैं, तो यह क्वेरी के तुरंत बाद भी हो सकता है - इससे पहले कि यह आपके पास वापस आ जाए - प्रश्न में कैश किए गए डेटा को कैश से निकाल दिया जाता है।

+0

यह एक आईएससीआई लक्ष्य है, इसलिए यह डिस्क कैश में कर्नेल द्वारा कैश किया गया है। मैं समय के साथ कैश उपयोग और विकास की निगरानी करना चाहता हूं। – wazoox

1

एक सूची का प्रतिनिधित्व करने के लिए आवश्यक जानकारी की मात्रा निराशावादी मामले के लिए है, जब सभी या लगभग सभी पृष्ठ वास्तव में रैम में हैं, बिटमैप से बहुत अधिक - प्रति प्रविष्टि कम से कम 64 बनाम 1 बिट्स। यदि ऐसा कोई एपीआई था, तो अपने 2 अरब पृष्ठों के बारे में पूछताछ करते समय, आपको जवाब में 16 जीबी डेटा प्राप्त करने के लिए तैयार रहना होगा। इसके अतिरिक्त, सूचियों-चर संरचनाओं को संभालने जैसे सूचियों को एक निश्चित-लंबाई सरणी को संभालने से अधिक जटिल है, इसलिए पुस्तकालय कार्य, विशेष रूप से निम्न-स्तरीय सिस्टम वाले, परेशानी से बचने के लिए होते हैं।

मुझे इस मामले में कार्यान्वयन (ओएस कैसे टीएलबी और सह के साथ इंटरैक्ट करता है) के बारे में पूरी तरह से यकीन नहीं है, लेकिन यह भी हो सकता है कि बिटमैप को भरने से भी आकार में अंतर हो सकता है ओएस के कारण एक सूची- और हार्डवेयर-स्तरीय संरचनाओं से जानकारी निकाली जाती है।

यदि आप बहुत अच्छी ग्रैन्युलरिटी के बारे में चिंतित नहीं हैं, तो आप /proc/<PID>/smaps पर एक नज़र डाल सकते हैं। प्रत्येक मैप किए गए क्षेत्र के लिए यह कुछ आंकड़े दिखाता है, जिसमें स्मृति में कितना लोड किया गया है (Rss फ़ील्ड)। यदि डिबगिंग के प्रयोजन के लिए आप एक फ़ाइल के कुछ क्षेत्रों को अलग mmap() कॉल (वास्तविक कार्य करने के लिए उपयोग किए जाने वाले मुख्य मैपिंग के अतिरिक्त) के साथ मैप करते हैं, तो आपको शायद smaps में अलग-अलग प्रविष्टियां मिलेंगी और इस प्रकार इन क्षेत्रों के लिए अलग-अलग आंकड़े देखेंगे। आप लगभग निश्चित रूप से अपने सिस्टम को मारने के बिना अरबों मैपिंग नहीं कर सकते हैं, लेकिन अगर फ़ाइल अच्छी तरह से संरचित है, तो शायद कुछ दर्जन अच्छी तरह से चुने गए क्षेत्रों के लिए अलग-अलग आंकड़े होने से आप जो उत्तरों ढूंढ रहे हैं उन्हें ढूंढने में आपकी सहायता कर सकते हैं।

+0

मैंने वास्तव में smaps कोशिश की। हालांकि किसी कारण से यह अन्य प्रक्रियाओं द्वारा मैप किए गए मेमोरी पेजों की रिपोर्ट नहीं करता है, इसलिए यह इस विशेष मामले में मेरी सहायता नहीं करता है। मैं वास्तव में क्या देख रहा हूं एमएमयू वर्चुअल-टू-भौतिक पते तालिका तक पहुंच है :) – wazoox

संबंधित मुद्दे