সি ++ ব্যবহার করে রানটাইমে মেমরির ব্যবহার কীভাবে পাবেন?


90

আমার প্রোগ্রামটি চলাকালীন আমার মেমের ব্যবহার ভিআইআরটি এবং আরএসই নেওয়া এবং সেগুলি প্রদর্শন করা দরকার।

আমি এখন পর্যন্ত যা চেষ্টা করেছি:

getrusage ( http://linux.die.net/man/2/getrusage )

int who = RUSAGE_SELF; 
struct rusage usage; 
int ret; 

ret=getrusage(who,&usage);

cout<<usage.ru_maxrss;

তবে আমি সর্বদা 0 পাই


4
এটি সিস্টেম নির্ভর - এটি প্রদর্শিত হয় যে আপনার সিস্টেম গেট্রাসেজের মাধ্যমে ম্যাক্সারগুলি প্রতিবেদন করতে সমর্থন করে না - আপনি কি বিতরণ ব্যবহার করছেন তা আমাদের বলতে পারেন?
tvanfosson

উত্তর:


79

লিনাক্সে, আমি কখনই একটি আইওএসটিএল () সমাধান খুঁজে পাইনি । আমাদের অ্যাপ্লিকেশনগুলির জন্য, আমরা / প্রোক / পিডে ফাইলগুলি পড়ার উপর ভিত্তি করে একটি সাধারণ ইউটিলিটি রুটিন কোড করেছি । এই ফাইলগুলির একটি রয়েছে যা বিভিন্ন ফলাফল দেয়। এখানে আমরা স্থিতিযুক্ত একটি এখানে রয়েছে (প্রশ্নটি সি ++ ট্যাগ করা হয়েছিল, এবং আমরা সি ++ কনস্ট্রাক্ট ব্যবহার করে I / O পরিচালনা করেছি, তবে আপনার যদি প্রয়োজন হয় তবে এটি সহজেই I / O রুটিনগুলির সাথে মানিয়ে নেওয়া উচিত):

#include <unistd.h>
#include <ios>
#include <iostream>
#include <fstream>
#include <string>

//////////////////////////////////////////////////////////////////////////////
//
// process_mem_usage(double &, double &) - takes two doubles by reference,
// attempts to read the system-dependent data for a process' virtual memory
// size and resident set size, and return the results in KB.
//
// On failure, returns 0.0, 0.0

void process_mem_usage(double& vm_usage, double& resident_set)
{
   using std::ios_base;
   using std::ifstream;
   using std::string;

   vm_usage     = 0.0;
   resident_set = 0.0;

   // 'file' stat seems to give the most reliable results
   //
   ifstream stat_stream("/proc/self/stat",ios_base::in);

   // dummy vars for leading entries in stat that we don't care about
   //
   string pid, comm, state, ppid, pgrp, session, tty_nr;
   string tpgid, flags, minflt, cminflt, majflt, cmajflt;
   string utime, stime, cutime, cstime, priority, nice;
   string O, itrealvalue, starttime;

   // the two fields we want
   //
   unsigned long vsize;
   long rss;

   stat_stream >> pid >> comm >> state >> ppid >> pgrp >> session >> tty_nr
               >> tpgid >> flags >> minflt >> cminflt >> majflt >> cmajflt
               >> utime >> stime >> cutime >> cstime >> priority >> nice
               >> O >> itrealvalue >> starttime >> vsize >> rss; // don't care about the rest

   stat_stream.close();

   long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
   vm_usage     = vsize / 1024.0;
   resident_set = rss * page_size_kb;
}

int main()
{
   using std::cout;
   using std::endl;

   double vm, rss;
   process_mem_usage(vm, rss);
   cout << "VM: " << vm << "; RSS: " << rss << endl;
}

বিভিন্ন * নিক্স প্ল্যাটফর্মের আওতায় আপনার / proc / স্ব / স্ট্যাটাক কাঠামোর কোনও গ্যারান্টি আছে? ... আমি নিশ্চিত নই, তবে হ্যাঁ - ভাল লাগবে।
বায়দা

ঠিক আছে, বেশ কয়েক বছর ধরে আমি বেশিরভাগ সোলারিস, এইচপি-ইউএক্স এবং লিনাক্স ব্যবহার করেছি। / প্রকোপ / স্ব / স্ট্যাট লিনাক্স-আইএসএম বলে মনে হচ্ছে। উপরের প্রোগ্রামটির মূল সংস্করণটিতে সোলারিসের জন্য # আইফ ব্লক ছিল কারণ এটির ভিন্নতা রয়েছে।
ডন ওয়েকফিল্ড 19

আমি ধরে নিচ্ছি যে ওপি কেবল প্রশ্ন ট্যাগিংয়ের ভিত্তিতে লিনাক্সের বিষয়ে চিন্তা করে। আপনি যতটা পড়বেন তত পড়া / প্রোক হবে। সোলারিসে আপনি kstat এর মাধ্যমে সমস্ত ধরণের স্টাফের তথ্যও পেতে পারেন (যদিও এটি অন্যান্য উপায়ে আপনি কী পেতে পারেন তা প্রায়শই প্রতিলিপি করে)।
stsquad

আমি পার্টিতে মাত্র 10 বছর দেরী হয়েছি, তবে আপনি কেন আমাকে বলবেন যে আপনি কেন 1024 এর চেয়ে 1024.0 দ্বারা ভার্সাই ভাগ করবেন?
a_river_in_canada

4
পুনরায়: why 1024.0?- এটি সংকলককে ডাবল FIRST এ রূপান্তর করতে এবং তারপরে দ্বিগুণ ফলাফল পাওয়ার জন্য বিভাজনটি করতে বলে। অন্য পছন্দ: vm_usage = vsize / 1024;প্রথমে বিভাজনটি করবে, (@ ডনওয়েকফিল্ডকে ইনটিমেটেড হিসাবে নির্ভুলতা হারাবে) এবং তারপরে ডাবল রূপান্তর করবে।
জেসি চিশলম

52

ডেভিড রবার্ট নাদাউ তার ওয়েবসাইটে প্রক্রিয়া বাসিন্দার সেট আকার (শারীরিক স্মৃতি ব্যবহার) পেতে একটি ভাল স্ব -সংযুক্ত মাল্টি-প্ল্যাটফর্ম সি ফাংশন রেখেছেন :

/*
 * Author:  David Robert Nadeau
 * Site:    http://NadeauSoftware.com/
 * License: Creative Commons Attribution 3.0 Unported License
 *          http://creativecommons.org/licenses/by/3.0/deed.en_US
 */

#if defined(_WIN32)
#include <windows.h>
#include <psapi.h>

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#include <sys/resource.h>

#if defined(__APPLE__) && defined(__MACH__)
#include <mach/mach.h>

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
#include <fcntl.h>
#include <procfs.h>

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
#include <stdio.h>

#endif

#else
#error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
#endif





/**
 * Returns the peak (maximum so far) resident set size (physical
 * memory use) measured in bytes, or zero if the value cannot be
 * determined on this OS.
 */
size_t getPeakRSS( )
{
#if defined(_WIN32)
    /* Windows -------------------------------------------------- */
    PROCESS_MEMORY_COUNTERS info;
    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
    return (size_t)info.PeakWorkingSetSize;

#elif (defined(_AIX) || defined(__TOS__AIX__)) || (defined(__sun__) || defined(__sun) || defined(sun) && (defined(__SVR4) || defined(__svr4__)))
    /* AIX and Solaris ------------------------------------------ */
    struct psinfo psinfo;
    int fd = -1;
    if ( (fd = open( "/proc/self/psinfo", O_RDONLY )) == -1 )
        return (size_t)0L;      /* Can't open? */
    if ( read( fd, &psinfo, sizeof(psinfo) ) != sizeof(psinfo) )
    {
        close( fd );
        return (size_t)0L;      /* Can't read? */
    }
    close( fd );
    return (size_t)(psinfo.pr_rssize * 1024L);

#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
    /* BSD, Linux, and OSX -------------------------------------- */
    struct rusage rusage;
    getrusage( RUSAGE_SELF, &rusage );
#if defined(__APPLE__) && defined(__MACH__)
    return (size_t)rusage.ru_maxrss;
#else
    return (size_t)(rusage.ru_maxrss * 1024L);
#endif

#else
    /* Unknown OS ----------------------------------------------- */
    return (size_t)0L;          /* Unsupported. */
#endif
}





/**
 * Returns the current resident set size (physical memory use) measured
 * in bytes, or zero if the value cannot be determined on this OS.
 */
size_t getCurrentRSS( )
{
#if defined(_WIN32)
    /* Windows -------------------------------------------------- */
    PROCESS_MEMORY_COUNTERS info;
    GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
    return (size_t)info.WorkingSetSize;

#elif defined(__APPLE__) && defined(__MACH__)
    /* OSX ------------------------------------------------------ */
    struct mach_task_basic_info info;
    mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
    if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
        (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
        return (size_t)0L;      /* Can't access? */
    return (size_t)info.resident_size;

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
    /* Linux ---------------------------------------------------- */
    long rss = 0L;
    FILE* fp = NULL;
    if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
        return (size_t)0L;      /* Can't open? */
    if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
    {
        fclose( fp );
        return (size_t)0L;      /* Can't read? */
    }
    fclose( fp );
    return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);

#else
    /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
    return (size_t)0L;          /* Unsupported. */
#endif
}

ব্যবহার

size_t currentSize = getCurrentRSS( );
size_t peakSize    = getPeakRSS( );

আরও আলোচনার জন্য, ওয়েবসাইটটি দেখুন, এটি কোনও সিস্টেমের শারীরিক মেমরির আকার পেতে একটি ফাংশন সরবরাহ করে


4
সুযোগ আরও ভাল যোগ #pragma comment(lib, "psapi.lib")হয়েছে #if defined(_WIN32)
ব্লাডমুন

4
@ ব্লাডমোন যদি কেউ উইন্ডোজ ব্যবহার করে তবে মাইক্রোসফ্ট সংকলক নয়? যে প্রগমা সংকলক ব্যর্থ করতে হবে।
অ্যাড্রিয়ান

এই কোডটি গুত্রুজ থেকে রুস :: রু_ম্যাক্সার্স ব্যবহার করেছে, যা ওপি তার পক্ষে কাজ করছে না বলে জানিয়েছে।
ফেসবুকে

21

পুরাতন:

ম্যাক্সার্স প্রক্রিয়াটির জন্য সর্বাধিক উপলভ্য মেমরিটি উল্লেখ করে। 0 এর অর্থ হল যে প্রক্রিয়াটির উপরে কোনও সীমা রাখা হয়নি। আপনি যা চান সম্ভবত শেয়ারড ডেটা ব্যবহার ru_idrss

নতুন: মনে হচ্ছে উপরেরগুলি আসলে কাজ করে না, কারণ কার্নেল বেশিরভাগ মান পূরণ করে না। কাজটি হ'ল প্রোকে তথ্য সংগ্রহ করা। যদিও এটি নিজের ভাগ করার পরিবর্তে, নিম্নরূপে লাইবপ্রোক (প্রোপসের অংশ) ব্যবহার করা সহজ:

// getrusage.c
#include <stdio.h>
#include <proc/readproc.h>

int main() {
  struct proc_t usage;
  look_up_our_self(&usage);
  printf("usage: %lu\n", usage.vsize);
}

" gcc -o getrusage getrusage.c -lproc" দিয়ে সংকলন করুন


4
লিনাক্সে উভয় ক্ষেত্রেই ক্ষেত্র উপলব্ধ নয়।
jmanning2k

4
এটি ভুল। ম্যাক্সার্স হ'ল প্রক্রিয়াটির সর্বোচ্চ মেমরির ব্যবহার, সর্বাধিক উপলব্ধ নয় - যা getrlimit (RLIMIT_DATA, & rl) হবে।
jmanning2k

4
#include <proc/readproc.h>সমাধান উবুন্টু অধীনে আমার জন্য কাজ করে মহান। আমাকে প্যাকেজ ইনস্টল করতে হয়েছিল libproc-devusage.vm_dataআমার যা প্রয়োজন তার কাছাকাছি পর্যাপ্ত পরিমাণ। আপনার মেমরির পরিসংখ্যানগুলির পছন্দটি এখানে নথিভুক্ত করা হয়েছে: /usr/include/proc/readproc.hআমি যেগুলি চেষ্টা করেছিলাম তা পৃষ্ঠাতে নয়, বাইটগুলিতে বলে মনে হয়। আমি মনে করি না যে আমার প্রক্রিয়া 46 মিলিয়ন পৃষ্ঠা ব্যবহার করেছিল। এই সমাধানটি লিনাক্সের অধীনে কাজ করে না এমন মন্তব্যগুলি বিপথগামী বলে মনে হচ্ছে।
অ্যালান স্টোকস

4
সঠিক লিঙ্কারটি হ'ল: -প্রক্রপস
সিম্বিয়েন্স

দুর্দান্ত কাজ করে, এটির একটি গ্রহণযোগ্য উত্তর হওয়া উচিত!
পেকভ

9

লিনাক্সে, আপনি যদি রান টাইম ব্যয় (ডিবাগিংয়ের জন্য) সামর্থ্য করতে পারেন তবে আপনি ম্যাসিফ টুল দিয়ে ভালগ্রাইন্ড ব্যবহার করতে পারেন:

http://valgrind.org/docs/manual/ms-manual.html

এটি ভারী ওজনযুক্ত, তবে খুব দরকারী।


8

ডন ওয়েকফিল্ড পদ্ধতির জন্য আরও মার্জিত উপায়:

#include <iostream>
#include <fstream>

using namespace std;

int main(){

    int tSize = 0, resident = 0, share = 0;
    ifstream buffer("/proc/self/statm");
    buffer >> tSize >> resident >> share;
    buffer.close();

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    double rss = resident * page_size_kb;
    cout << "RSS - " << rss << " kB\n";

    double shared_mem = share * page_size_kb;
    cout << "Shared Memory - " << shared_mem << " kB\n";

    cout << "Private Memory - " << rss - shared_mem << "kB\n";
    return 0;
}

7

বিদ্যমান উত্তরগুলি সঠিক মান কীভাবে পাওয়া যায় তার জন্য আরও ভাল তবে আমি কেন অন্তত তা বুঝতে পারি যে কেন গথ্রাসেজ আপনার পক্ষে কাজ করছে না।

ম্যান 2 গেট্রাসেজ:

উপরোক্ত স্ট্রাক্ট [rusage] BSD 4.3 রেনো থেকে নেওয়া হয়েছিল। সমস্ত ক্ষেত্র লিনাক্সের অধীনে অর্থবহ নয়। এই মুহুর্তে (লিনাক্স ২.৪, ২.6) কেবলমাত্র ক্ষেত্রগুলি রু_উইমটাইম, রু_সটাইম, রু_মিনফল্ট, রু_মাজফল্ট এবং রু_সনপ পরিচালনা করে।


3

আপনার
উপায়ের অতিরিক্ত হিসাবে আপনি সিস্টেম পিএস কমান্ড কল করতে পারেন এবং এর আউটপুট থেকে মেমরির ব্যবহার পেতে পারেন।
অথবা / প্রোক / পিডের তথ্য পড়ুন (পিআইওসিপিএসআইএনফো স্ট্রাক্ট দেখুন)


PIOCPSINFO সত্যিই আমার ব্যবহার করা কোনও লিনাক্স উপলভ্য নয়। / প্রোক / পিড থেকে পড়া বেশ সাধারণ। আমি একটি উত্তরে লিনাক্সের জন্য উদাহরণ কোড পোস্ট করব ...
ডন ওয়েকফিল্ড

হ্যাঁ / প্রোক / পিড স্ট্রাকচারগুলি আলাদা আলাদা * নিক প্ল্যাটফর্মগুলিতে পৃথক হতে পারে তবে আপনার যদি পিওসিপিএসআইএনএফও থাকে তবে এটি কোনও বিষয় নয়। আমার এমন পরিস্থিতি হয়েছিল যখন এই কাঠামোটি কিছু সোলারিস সংস্করণে সংজ্ঞায়িত করা হয়নি .. আমি এই ক্ষেত্রে পিএস আউটপুট ব্যবহার করেছি।
বায়দা

2

আপনার সিস্টেমে একটি ফাইল রয়েছে /proc/self/statm। প্রোক ফাইল সিস্টেমটি একটি সিউডো-ফাইল সিস্টেম যা কার্নেল ডেটা স্ট্রাকচারকে ইন্টারফেস সরবরাহ করে। এই ফাইলটিতে কলামগুলিতে আপনার প্রয়োজনীয় তথ্য রয়েছে কেবলমাত্র পৃথক পূর্ণসংখ্যার সাথে space

কলাম নম্বর:

  1. = মোট প্রোগ্রামের আকার (VmSize in / proc / [pid] / status)

  2. = আবাসিক সেট আকার (ভিএমআরএসএস ইন / প্রোক / [পিআইডি] / স্ট্যাটাসে)

আরও তথ্যের জন্য লিঙ্কটি দেখুন


1

আমি এটি করতে অন্য উপায় ব্যবহার করছি এবং এটি বাস্তববাদী মনে হচ্ছে। আমি যা করি তা হ'ল আমি getpid () ফাংশন দ্বারা প্রক্রিয়াটির পিআইডি পেয়েছি এবং তারপরে আমি / proc / pid / stat ফাইলটি ব্যবহার করি। আমি বিশ্বাস করি স্ট্যাটাস ফাইলের 23 তম কলামটি vmsize (ডন পোস্টে দেখুন)। আপনি কোডটিতে যেখানেই প্রয়োজন ফাইলটি থেকে vmsize পড়তে পারেন। আপনি যদি বিস্মিত হন যে কোনও কোডের স্নিপেট মেমোরিটি কতটা ব্যবহার করতে পারে, আপনি সেই ফাইলটি স্নিপেটের আগে একবার এবং পরে একবার পড়তে পারেন এবং আপনি একে অপরের থেকে বিয়োগ করতে পারেন।


1

কম ভেরিয়েবল সহ ডন ডাব্লু এর সমাধানের ভিত্তিতে।

void process_mem_usage(double& vm_usage, double& resident_set)
{
    vm_usage     = 0.0;
    resident_set = 0.0;

    // the two fields we want
    unsigned long vsize;
    long rss;
    {
        std::string ignore;
        std::ifstream ifs("/proc/self/stat", std::ios_base::in);
        ifs >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
                >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
                >> ignore >> ignore >> vsize >> rss;
    }

    long page_size_kb = sysconf(_SC_PAGE_SIZE) / 1024; // in case x86-64 is configured to use 2MB pages
    vm_usage = vsize / 1024.0;
    resident_set = rss * page_size_kb;
}

0

ব্যবহৃত সর্বাধিক স্মৃতি মাপার জন্য আমি একটি লিনাক্স অ্যাপ্লিকেশন সন্ধান করছিলাম। ভালগ্রাইন্ড একটি দুর্দান্ত সরঞ্জাম, তবে আমার চেয়ে আমি আরও বেশি তথ্য দিচ্ছিলাম। টিএসটাইমটি আমার কাছে পাওয়া সেরা সরঞ্জাম বলে মনে হয়েছিল। এটি "উচ্চ জল" মেমরির ব্যবহার (আরএসএস এবং ভার্চুয়াল) পরিমাপ করে। এই উত্তর দেখুন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.