Thread: [htop-general] Request: adding dirty memory to memory meter
Brought to you by:
loderunner
From: Richard B. <rb...@sc...> - 2013-01-29 17:26:09
|
Hello, What would you fellow htop users think about adding the amount of dirty pages to the memory meter ? Also, I personally consider it much more important than separating buffer from cache memory (these could simply be merged into "cached" memory altogether). What's your opinion on this ? -- Richard Braun |
From: Seth <ht...@se...> - 2013-01-29 19:11:44
|
On 01/29/2013 06:10 PM, Richard Braun wrote: > Hello, > > What would you fellow htop users think about adding the amount of dirty > pages to the memory meter ? Also, I personally consider it much more > important than separating buffer from cache memory (these could simply > be merged into "cached" memory altogether). > > What's your opinion on this ? > I think it's interesting enough to make me curious. Any chance you could whip up a patch? |
From: Richard B. <rb...@sc...> - 2013-01-30 20:05:15
|
Monitoring the amount of dirty memory helps understanding how memory and I/O behave depending on the workload. This can in turn be used (mostly by system administrators and advanced users) to tune some VM parameters, such as vm.dirty_background_ratio and vm.dirty_ratio. The new "dirty" value reported in the memory meter actually includes both the Dirty (waiting to be written back) and Writeback (being written back) counters of the meminfo procfs file. In order to avoid consuming too much screen space, the previous "buffers" and "cache" values are merged in the latter, which now stands for clean cached memory. Total memory is then divided between "used", "dirty", "cached" (clean), and unused. --- CRT.c | 14 +++++++------- CRT.h | 2 +- MemoryMeter.c | 19 ++++++++++--------- ProcessList.c | 10 ++++++++++ ProcessList.h | 2 ++ htop.c | 2 +- 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/CRT.c b/CRT.c index 3a1eb91..00e95f2 100644 --- a/CRT.c +++ b/CRT.c @@ -83,7 +83,7 @@ typedef enum ColorElements_ { GRAPH_8, GRAPH_9, MEMORY_USED, - MEMORY_BUFFERS, + MEMORY_DIRTY, MEMORY_CACHE, LOAD, LOAD_AVERAGE_FIFTEEN, @@ -281,7 +281,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = A_DIM; CRT_colors[GRAPH_9] = A_DIM; CRT_colors[MEMORY_USED] = A_BOLD; - CRT_colors[MEMORY_BUFFERS] = A_NORMAL; + CRT_colors[MEMORY_DIRTY] = A_NORMAL; CRT_colors[MEMORY_CACHE] = A_NORMAL; CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM; CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; @@ -342,7 +342,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = ColorPair(Yellow,White); CRT_colors[GRAPH_9] = ColorPair(Yellow,White); CRT_colors[MEMORY_USED] = ColorPair(Green,White); - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White); + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,White); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White); @@ -403,7 +403,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = ColorPair(Yellow,Black); CRT_colors[GRAPH_9] = ColorPair(Yellow,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black); - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black); + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black); @@ -464,7 +464,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue); - CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue); + CRT_colors[MEMORY_DIRTY] = A_BOLD | ColorPair(Cyan,Blue); CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue); CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue); CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue); @@ -525,7 +525,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = ColorPair(Blue,Black); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black); - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black); CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black); @@ -587,7 +587,7 @@ void CRT_setColors(int colorScheme) { CRT_colors[GRAPH_8] = ColorPair(Blue,Black); CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); CRT_colors[MEMORY_USED] = ColorPair(Green,Black); - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black); CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; diff --git a/CRT.h b/CRT.h index f7d4d72..22125e2 100644 --- a/CRT.h +++ b/CRT.h @@ -75,7 +75,7 @@ typedef enum ColorElements_ { GRAPH_8, GRAPH_9, MEMORY_USED, - MEMORY_BUFFERS, + MEMORY_DIRTY, MEMORY_CACHE, LOAD, LOAD_AVERAGE_FIFTEEN, diff --git a/MemoryMeter.c b/MemoryMeter.c index eca0442..0f59808 100644 --- a/MemoryMeter.c +++ b/MemoryMeter.c @@ -22,17 +22,18 @@ in the source distribution for its full text. }*/ int MemoryMeter_attributes[] = { - MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE + MEMORY_USED, MEMORY_DIRTY, MEMORY_CACHE }; static void MemoryMeter_setValues(Meter* this, char* buffer, int size) { long int usedMem = this->pl->usedMem; - long int buffersMem = this->pl->buffersMem; - long int cachedMem = this->pl->cachedMem; - usedMem -= buffersMem + cachedMem; + long int dirtyMem = this->pl->dirtyMem + this->pl->writebackMem; + long int cachedMem = this->pl->buffersMem + this->pl->cachedMem; + usedMem -= cachedMem; + cachedMem -= dirtyMem; this->total = this->pl->totalMem; this->values[0] = usedMem; - this->values[1] = buffersMem; + this->values[1] = dirtyMem; this->values[2] = cachedMem; snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024); } @@ -43,7 +44,7 @@ static void MemoryMeter_display(Object* cast, RichString* out) { int k = 1024; const char* format = "%ldM "; long int totalMem = this->total / k; long int usedMem = this->values[0] / k; - long int buffersMem = this->values[1] / k; + long int dirtyMem = this->values[1] / k; long int cachedMem = this->values[2] / k; RichString_write(out, CRT_colors[METER_TEXT], ":"); sprintf(buffer, format, totalMem); @@ -51,9 +52,9 @@ static void MemoryMeter_display(Object* cast, RichString* out) { sprintf(buffer, format, usedMem); RichString_append(out, CRT_colors[METER_TEXT], "used:"); RichString_append(out, CRT_colors[MEMORY_USED], buffer); - sprintf(buffer, format, buffersMem); - RichString_append(out, CRT_colors[METER_TEXT], "buffers:"); - RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer); + sprintf(buffer, format, dirtyMem); + RichString_append(out, CRT_colors[METER_TEXT], "dirty:"); + RichString_append(out, CRT_colors[MEMORY_DIRTY], buffer); sprintf(buffer, format, cachedMem); RichString_append(out, CRT_colors[METER_TEXT], "cache:"); RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); diff --git a/ProcessList.c b/ProcessList.c index 99a6512..94a9a5e 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -127,6 +127,8 @@ typedef struct ProcessList_ { unsigned long long int sharedMem; unsigned long long int buffersMem; unsigned long long int cachedMem; + unsigned long long int dirtyMem; + unsigned long long int writebackMem; unsigned long long int totalSwap; unsigned long long int usedSwap; unsigned long long int freeSwap; @@ -788,6 +790,14 @@ void ProcessList_scan(ProcessList* this) { if (String_startsWith(buffer, "Cached:")) sscanf(buffer, "Cached: %llu kB", &this->cachedMem); break; + case 'D': + if (String_startsWith(buffer, "Dirty:")) + sscanf(buffer, "Dirty: %llu kB", &this->dirtyMem); + break; + case 'W': + if (String_startsWith(buffer, "Writeback:")) + sscanf(buffer, "Writeback: %llu kB", &this->writebackMem); + break; case 'S': if (String_startsWith(buffer, "SwapTotal:")) sscanf(buffer, "SwapTotal: %llu kB", &this->totalSwap); diff --git a/ProcessList.h b/ProcessList.h index e410ae2..cdc4c4e 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -110,6 +110,8 @@ typedef struct ProcessList_ { unsigned long long int sharedMem; unsigned long long int buffersMem; unsigned long long int cachedMem; + unsigned long long int dirtyMem; + unsigned long long int writebackMem; unsigned long long int totalSwap; unsigned long long int usedSwap; unsigned long long int freeSwap; diff --git a/htop.c b/htop.c index cdee8ee..220aa8e 100644 --- a/htop.c +++ b/htop.c @@ -102,7 +102,7 @@ static void showHelp(ProcessList* pl) { mvaddstr(4, 0, "Memory bar: "); addattrstr(CRT_colors[BAR_BORDER], "["); addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); - addattrstr(CRT_colors[MEMORY_BUFFERS], "buffers"); addstr("/"); + addattrstr(CRT_colors[MEMORY_DIRTY], "dirty"); addstr("/"); addattrstr(CRT_colors[MEMORY_CACHE], "cache"); addattrstr(CRT_colors[BAR_SHADOW], " used/total"); addattrstr(CRT_colors[BAR_BORDER], "]"); -- 1.7.2.5 |
From: Seth <ht...@se...> - 2013-01-30 20:30:52
|
Nice work. Patch applies cleanly to ubuntu 12.10 packaged version. I will run with this for a while to see what it does for me. (Note I'm not affiliated with this project, so my attention is in no way official.) Seth On 01/30/2013 09:05 PM, Richard Braun wrote: > Monitoring the amount of dirty memory helps understanding how memory and > I/O behave depending on the workload. This can in turn be used (mostly > by system administrators and advanced users) to tune some VM parameters, > such as vm.dirty_background_ratio and vm.dirty_ratio. > > The new "dirty" value reported in the memory meter actually includes > both the Dirty (waiting to be written back) and Writeback (being written > back) counters of the meminfo procfs file. In order to avoid consuming > too much screen space, the previous "buffers" and "cache" values are > merged in the latter, which now stands for clean cached memory. Total > memory is then divided between "used", "dirty", "cached" (clean), and > unused. > --- > CRT.c | 14 +++++++------- > CRT.h | 2 +- > MemoryMeter.c | 19 ++++++++++--------- > ProcessList.c | 10 ++++++++++ > ProcessList.h | 2 ++ > htop.c | 2 +- > 6 files changed, 31 insertions(+), 18 deletions(-) > > diff --git a/CRT.c b/CRT.c > index 3a1eb91..00e95f2 100644 > --- a/CRT.c > +++ b/CRT.c > @@ -83,7 +83,7 @@ typedef enum ColorElements_ { > GRAPH_8, > GRAPH_9, > MEMORY_USED, > - MEMORY_BUFFERS, > + MEMORY_DIRTY, > MEMORY_CACHE, > LOAD, > LOAD_AVERAGE_FIFTEEN, > @@ -281,7 +281,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = A_DIM; > CRT_colors[GRAPH_9] = A_DIM; > CRT_colors[MEMORY_USED] = A_BOLD; > - CRT_colors[MEMORY_BUFFERS] = A_NORMAL; > + CRT_colors[MEMORY_DIRTY] = A_NORMAL; > CRT_colors[MEMORY_CACHE] = A_NORMAL; > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM; > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; > @@ -342,7 +342,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Yellow,White); > CRT_colors[GRAPH_9] = ColorPair(Yellow,White); > CRT_colors[MEMORY_USED] = ColorPair(Green,White); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,White); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White); > @@ -403,7 +403,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Yellow,Black); > CRT_colors[GRAPH_9] = ColorPair(Yellow,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black); > @@ -464,7 +464,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue); > - CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue); > + CRT_colors[MEMORY_DIRTY] = A_BOLD | ColorPair(Cyan,Blue); > CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue); > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue); > @@ -525,7 +525,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Blue,Black); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black); > @@ -587,7 +587,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Blue,Black); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; > diff --git a/CRT.h b/CRT.h > index f7d4d72..22125e2 100644 > --- a/CRT.h > +++ b/CRT.h > @@ -75,7 +75,7 @@ typedef enum ColorElements_ { > GRAPH_8, > GRAPH_9, > MEMORY_USED, > - MEMORY_BUFFERS, > + MEMORY_DIRTY, > MEMORY_CACHE, > LOAD, > LOAD_AVERAGE_FIFTEEN, > diff --git a/MemoryMeter.c b/MemoryMeter.c > index eca0442..0f59808 100644 > --- a/MemoryMeter.c > +++ b/MemoryMeter.c > @@ -22,17 +22,18 @@ in the source distribution for its full text. > }*/ > > int MemoryMeter_attributes[] = { > - MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE > + MEMORY_USED, MEMORY_DIRTY, MEMORY_CACHE > }; > > static void MemoryMeter_setValues(Meter* this, char* buffer, int size) { > long int usedMem = this->pl->usedMem; > - long int buffersMem = this->pl->buffersMem; > - long int cachedMem = this->pl->cachedMem; > - usedMem -= buffersMem + cachedMem; > + long int dirtyMem = this->pl->dirtyMem + this->pl->writebackMem; > + long int cachedMem = this->pl->buffersMem + this->pl->cachedMem; > + usedMem -= cachedMem; > + cachedMem -= dirtyMem; > this->total = this->pl->totalMem; > this->values[0] = usedMem; > - this->values[1] = buffersMem; > + this->values[1] = dirtyMem; > this->values[2] = cachedMem; > snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024); > } > @@ -43,7 +44,7 @@ static void MemoryMeter_display(Object* cast, RichString* out) { > int k = 1024; const char* format = "%ldM "; > long int totalMem = this->total / k; > long int usedMem = this->values[0] / k; > - long int buffersMem = this->values[1] / k; > + long int dirtyMem = this->values[1] / k; > long int cachedMem = this->values[2] / k; > RichString_write(out, CRT_colors[METER_TEXT], ":"); > sprintf(buffer, format, totalMem); > @@ -51,9 +52,9 @@ static void MemoryMeter_display(Object* cast, RichString* out) { > sprintf(buffer, format, usedMem); > RichString_append(out, CRT_colors[METER_TEXT], "used:"); > RichString_append(out, CRT_colors[MEMORY_USED], buffer); > - sprintf(buffer, format, buffersMem); > - RichString_append(out, CRT_colors[METER_TEXT], "buffers:"); > - RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer); > + sprintf(buffer, format, dirtyMem); > + RichString_append(out, CRT_colors[METER_TEXT], "dirty:"); > + RichString_append(out, CRT_colors[MEMORY_DIRTY], buffer); > sprintf(buffer, format, cachedMem); > RichString_append(out, CRT_colors[METER_TEXT], "cache:"); > RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); > diff --git a/ProcessList.c b/ProcessList.c > index 99a6512..94a9a5e 100644 > --- a/ProcessList.c > +++ b/ProcessList.c > @@ -127,6 +127,8 @@ typedef struct ProcessList_ { > unsigned long long int sharedMem; > unsigned long long int buffersMem; > unsigned long long int cachedMem; > + unsigned long long int dirtyMem; > + unsigned long long int writebackMem; > unsigned long long int totalSwap; > unsigned long long int usedSwap; > unsigned long long int freeSwap; > @@ -788,6 +790,14 @@ void ProcessList_scan(ProcessList* this) { > if (String_startsWith(buffer, "Cached:")) > sscanf(buffer, "Cached: %llu kB", &this->cachedMem); > break; > + case 'D': > + if (String_startsWith(buffer, "Dirty:")) > + sscanf(buffer, "Dirty: %llu kB", &this->dirtyMem); > + break; > + case 'W': > + if (String_startsWith(buffer, "Writeback:")) > + sscanf(buffer, "Writeback: %llu kB", &this->writebackMem); > + break; > case 'S': > if (String_startsWith(buffer, "SwapTotal:")) > sscanf(buffer, "SwapTotal: %llu kB", &this->totalSwap); > diff --git a/ProcessList.h b/ProcessList.h > index e410ae2..cdc4c4e 100644 > --- a/ProcessList.h > +++ b/ProcessList.h > @@ -110,6 +110,8 @@ typedef struct ProcessList_ { > unsigned long long int sharedMem; > unsigned long long int buffersMem; > unsigned long long int cachedMem; > + unsigned long long int dirtyMem; > + unsigned long long int writebackMem; > unsigned long long int totalSwap; > unsigned long long int usedSwap; > unsigned long long int freeSwap; > diff --git a/htop.c b/htop.c > index cdee8ee..220aa8e 100644 > --- a/htop.c > +++ b/htop.c > @@ -102,7 +102,7 @@ static void showHelp(ProcessList* pl) { > mvaddstr(4, 0, "Memory bar: "); > addattrstr(CRT_colors[BAR_BORDER], "["); > addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); > - addattrstr(CRT_colors[MEMORY_BUFFERS], "buffers"); addstr("/"); > + addattrstr(CRT_colors[MEMORY_DIRTY], "dirty"); addstr("/"); > addattrstr(CRT_colors[MEMORY_CACHE], "cache"); > addattrstr(CRT_colors[BAR_SHADOW], " used/total"); > addattrstr(CRT_colors[BAR_BORDER], "]"); > -- 1.7.2.5 |
From: Hisham <h...@hi...> - 2013-01-30 23:14:11
|
Richard, Thank you for the patch. I'm a bit busy right now but I'll look closely into it in the next few days. Seth and everyone else reading this, all feedback regarding the behavior and usefulness of this patch is extremely welcome. This is a major UI change if we adopt this, so I need to be sure it's for the best (I'll most likely use it myself for a while to try it out when I get around to test it.) Thank you, -- Hisham On Wed, Jan 30, 2013 at 6:30 PM, Seth <ht...@se...> wrote: > Nice work. Patch applies cleanly to ubuntu 12.10 packaged version. I > will run with this for a while to see what it does for me. > > (Note I'm not affiliated with this project, so my attention is in no way > official.) > Seth > > On 01/30/2013 09:05 PM, Richard Braun wrote: >> Monitoring the amount of dirty memory helps understanding how memory and >> I/O behave depending on the workload. This can in turn be used (mostly >> by system administrators and advanced users) to tune some VM parameters, >> such as vm.dirty_background_ratio and vm.dirty_ratio. >> >> The new "dirty" value reported in the memory meter actually includes >> both the Dirty (waiting to be written back) and Writeback (being written >> back) counters of the meminfo procfs file. In order to avoid consuming >> too much screen space, the previous "buffers" and "cache" values are >> merged in the latter, which now stands for clean cached memory. Total >> memory is then divided between "used", "dirty", "cached" (clean), and >> unused. >> --- >> CRT.c | 14 +++++++------- >> CRT.h | 2 +- >> MemoryMeter.c | 19 ++++++++++--------- >> ProcessList.c | 10 ++++++++++ >> ProcessList.h | 2 ++ >> htop.c | 2 +- >> 6 files changed, 31 insertions(+), 18 deletions(-) >> >> diff --git a/CRT.c b/CRT.c >> index 3a1eb91..00e95f2 100644 >> --- a/CRT.c >> +++ b/CRT.c >> @@ -83,7 +83,7 @@ typedef enum ColorElements_ { >> GRAPH_8, >> GRAPH_9, >> MEMORY_USED, >> - MEMORY_BUFFERS, >> + MEMORY_DIRTY, >> MEMORY_CACHE, >> LOAD, >> LOAD_AVERAGE_FIFTEEN, >> @@ -281,7 +281,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = A_DIM; >> CRT_colors[GRAPH_9] = A_DIM; >> CRT_colors[MEMORY_USED] = A_BOLD; >> - CRT_colors[MEMORY_BUFFERS] = A_NORMAL; >> + CRT_colors[MEMORY_DIRTY] = A_NORMAL; >> CRT_colors[MEMORY_CACHE] = A_NORMAL; >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM; >> CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; >> @@ -342,7 +342,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = ColorPair(Yellow,White); >> CRT_colors[GRAPH_9] = ColorPair(Yellow,White); >> CRT_colors[MEMORY_USED] = ColorPair(Green,White); >> - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White); >> + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,White); >> CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White); >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White); >> CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White); >> @@ -403,7 +403,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = ColorPair(Yellow,Black); >> CRT_colors[GRAPH_9] = ColorPair(Yellow,Black); >> CRT_colors[MEMORY_USED] = ColorPair(Green,Black); >> - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black); >> + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,Black); >> CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black); >> CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black); >> @@ -464,7 +464,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = A_BOLD | ColorPair(Yellow,Blue); >> CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue); >> CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue); >> - CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue); >> + CRT_colors[MEMORY_DIRTY] = A_BOLD | ColorPair(Cyan,Blue); >> CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue); >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue); >> CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue); >> @@ -525,7 +525,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = ColorPair(Blue,Black); >> CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); >> CRT_colors[MEMORY_USED] = ColorPair(Green,Black); >> - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); >> + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); >> CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black); >> CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black); >> @@ -587,7 +587,7 @@ void CRT_setColors(int colorScheme) { >> CRT_colors[GRAPH_8] = ColorPair(Blue,Black); >> CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); >> CRT_colors[MEMORY_USED] = ColorPair(Green,Black); >> - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); >> + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); >> CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); >> CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black); >> CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; >> diff --git a/CRT.h b/CRT.h >> index f7d4d72..22125e2 100644 >> --- a/CRT.h >> +++ b/CRT.h >> @@ -75,7 +75,7 @@ typedef enum ColorElements_ { >> GRAPH_8, >> GRAPH_9, >> MEMORY_USED, >> - MEMORY_BUFFERS, >> + MEMORY_DIRTY, >> MEMORY_CACHE, >> LOAD, >> LOAD_AVERAGE_FIFTEEN, >> diff --git a/MemoryMeter.c b/MemoryMeter.c >> index eca0442..0f59808 100644 >> --- a/MemoryMeter.c >> +++ b/MemoryMeter.c >> @@ -22,17 +22,18 @@ in the source distribution for its full text. >> }*/ >> >> int MemoryMeter_attributes[] = { >> - MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE >> + MEMORY_USED, MEMORY_DIRTY, MEMORY_CACHE >> }; >> >> static void MemoryMeter_setValues(Meter* this, char* buffer, int size) { >> long int usedMem = this->pl->usedMem; >> - long int buffersMem = this->pl->buffersMem; >> - long int cachedMem = this->pl->cachedMem; >> - usedMem -= buffersMem + cachedMem; >> + long int dirtyMem = this->pl->dirtyMem + this->pl->writebackMem; >> + long int cachedMem = this->pl->buffersMem + this->pl->cachedMem; >> + usedMem -= cachedMem; >> + cachedMem -= dirtyMem; >> this->total = this->pl->totalMem; >> this->values[0] = usedMem; >> - this->values[1] = buffersMem; >> + this->values[1] = dirtyMem; >> this->values[2] = cachedMem; >> snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024); >> } >> @@ -43,7 +44,7 @@ static void MemoryMeter_display(Object* cast, RichString* out) { >> int k = 1024; const char* format = "%ldM "; >> long int totalMem = this->total / k; >> long int usedMem = this->values[0] / k; >> - long int buffersMem = this->values[1] / k; >> + long int dirtyMem = this->values[1] / k; >> long int cachedMem = this->values[2] / k; >> RichString_write(out, CRT_colors[METER_TEXT], ":"); >> sprintf(buffer, format, totalMem); >> @@ -51,9 +52,9 @@ static void MemoryMeter_display(Object* cast, RichString* out) { >> sprintf(buffer, format, usedMem); >> RichString_append(out, CRT_colors[METER_TEXT], "used:"); >> RichString_append(out, CRT_colors[MEMORY_USED], buffer); >> - sprintf(buffer, format, buffersMem); >> - RichString_append(out, CRT_colors[METER_TEXT], "buffers:"); >> - RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer); >> + sprintf(buffer, format, dirtyMem); >> + RichString_append(out, CRT_colors[METER_TEXT], "dirty:"); >> + RichString_append(out, CRT_colors[MEMORY_DIRTY], buffer); >> sprintf(buffer, format, cachedMem); >> RichString_append(out, CRT_colors[METER_TEXT], "cache:"); >> RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); >> diff --git a/ProcessList.c b/ProcessList.c >> index 99a6512..94a9a5e 100644 >> --- a/ProcessList.c >> +++ b/ProcessList.c >> @@ -127,6 +127,8 @@ typedef struct ProcessList_ { >> unsigned long long int sharedMem; >> unsigned long long int buffersMem; >> unsigned long long int cachedMem; >> + unsigned long long int dirtyMem; >> + unsigned long long int writebackMem; >> unsigned long long int totalSwap; >> unsigned long long int usedSwap; >> unsigned long long int freeSwap; >> @@ -788,6 +790,14 @@ void ProcessList_scan(ProcessList* this) { >> if (String_startsWith(buffer, "Cached:")) >> sscanf(buffer, "Cached: %llu kB", &this->cachedMem); >> break; >> + case 'D': >> + if (String_startsWith(buffer, "Dirty:")) >> + sscanf(buffer, "Dirty: %llu kB", &this->dirtyMem); >> + break; >> + case 'W': >> + if (String_startsWith(buffer, "Writeback:")) >> + sscanf(buffer, "Writeback: %llu kB", &this->writebackMem); >> + break; >> case 'S': >> if (String_startsWith(buffer, "SwapTotal:")) >> sscanf(buffer, "SwapTotal: %llu kB", &this->totalSwap); >> diff --git a/ProcessList.h b/ProcessList.h >> index e410ae2..cdc4c4e 100644 >> --- a/ProcessList.h >> +++ b/ProcessList.h >> @@ -110,6 +110,8 @@ typedef struct ProcessList_ { >> unsigned long long int sharedMem; >> unsigned long long int buffersMem; >> unsigned long long int cachedMem; >> + unsigned long long int dirtyMem; >> + unsigned long long int writebackMem; >> unsigned long long int totalSwap; >> unsigned long long int usedSwap; >> unsigned long long int freeSwap; >> diff --git a/htop.c b/htop.c >> index cdee8ee..220aa8e 100644 >> --- a/htop.c >> +++ b/htop.c >> @@ -102,7 +102,7 @@ static void showHelp(ProcessList* pl) { >> mvaddstr(4, 0, "Memory bar: "); >> addattrstr(CRT_colors[BAR_BORDER], "["); >> addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); >> - addattrstr(CRT_colors[MEMORY_BUFFERS], "buffers"); addstr("/"); >> + addattrstr(CRT_colors[MEMORY_DIRTY], "dirty"); addstr("/"); >> addattrstr(CRT_colors[MEMORY_CACHE], "cache"); >> addattrstr(CRT_colors[BAR_SHADOW], " used/total"); >> addattrstr(CRT_colors[BAR_BORDER], "]"); >> -- 1.7.2.5 > > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_jan > _______________________________________________ > htop-general mailing list > hto...@li... > https://lists.sourceforge.net/lists/listinfo/htop-general |
From: Seth <ht...@se...> - 2013-01-31 00:10:54
|
On 01/31/2013 12:13 AM, Hisham wrote: > This is a > major UI change if we adopt this It could be governed by a flag, maybe |
From: Seth <ht...@se...> - 2013-02-06 13:54:09
|
I've been running with the patch for some time now. Quite simply, it works as advertised, I think. On the functional side of things, I haven't found out what the "Dirty" measure is useful for, for me. I can imagine (as you state) that particular brand of sysadmin tasks (virtualization hosts) might have a user for this. On my workstation, and under the most extreme of loads I could think of, the most I've seen reported 'Dirty" is 11MiB. In this light, I'd prefer this to be a switchable option (one more 'memory bar' display setting, or perhaps a command line option). I feel the distinction buffers/cache is more meaningful, mainly because the numbers aren't nearly as volatile. For my IO metering needs I use the IO* fields or usually vmstat Is there anything I'm missing? Cheers, Seth On 01/30/2013 09:05 PM, Richard Braun wrote: > Monitoring the amount of dirty memory helps understanding how memory and > I/O behave depending on the workload. This can in turn be used (mostly > by system administrators and advanced users) to tune some VM parameters, > such as vm.dirty_background_ratio and vm.dirty_ratio. > > The new "dirty" value reported in the memory meter actually includes > both the Dirty (waiting to be written back) and Writeback (being written > back) counters of the meminfo procfs file. In order to avoid consuming > too much screen space, the previous "buffers" and "cache" values are > merged in the latter, which now stands for clean cached memory. Total > memory is then divided between "used", "dirty", "cached" (clean), and > unused. > --- > CRT.c | 14 +++++++------- > CRT.h | 2 +- > MemoryMeter.c | 19 ++++++++++--------- > ProcessList.c | 10 ++++++++++ > ProcessList.h | 2 ++ > htop.c | 2 +- > 6 files changed, 31 insertions(+), 18 deletions(-) > > diff --git a/CRT.c b/CRT.c > index 3a1eb91..00e95f2 100644 > --- a/CRT.c > +++ b/CRT.c > @@ -83,7 +83,7 @@ typedef enum ColorElements_ { > GRAPH_8, > GRAPH_9, > MEMORY_USED, > - MEMORY_BUFFERS, > + MEMORY_DIRTY, > MEMORY_CACHE, > LOAD, > LOAD_AVERAGE_FIFTEEN, > @@ -281,7 +281,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = A_DIM; > CRT_colors[GRAPH_9] = A_DIM; > CRT_colors[MEMORY_USED] = A_BOLD; > - CRT_colors[MEMORY_BUFFERS] = A_NORMAL; > + CRT_colors[MEMORY_DIRTY] = A_NORMAL; > CRT_colors[MEMORY_CACHE] = A_NORMAL; > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_DIM; > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; > @@ -342,7 +342,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Yellow,White); > CRT_colors[GRAPH_9] = ColorPair(Yellow,White); > CRT_colors[MEMORY_USED] = ColorPair(Green,White); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,White); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,White); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,White); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,White); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,White); > @@ -403,7 +403,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Yellow,Black); > CRT_colors[GRAPH_9] = ColorPair(Yellow,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Cyan,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Cyan,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Black,Black); > @@ -464,7 +464,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[MEMORY_USED] = A_BOLD | ColorPair(Green,Blue); > - CRT_colors[MEMORY_BUFFERS] = A_BOLD | ColorPair(Cyan,Blue); > + CRT_colors[MEMORY_DIRTY] = A_BOLD | ColorPair(Cyan,Blue); > CRT_colors[MEMORY_CACHE] = A_BOLD | ColorPair(Yellow,Blue); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Blue); > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL | ColorPair(White,Blue); > @@ -525,7 +525,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Blue,Black); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = ColorPair(Green,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = ColorPair(Green,Black); > @@ -587,7 +587,7 @@ void CRT_setColors(int colorScheme) { > CRT_colors[GRAPH_8] = ColorPair(Blue,Black); > CRT_colors[GRAPH_9] = A_BOLD | ColorPair(Black,Black); > CRT_colors[MEMORY_USED] = ColorPair(Green,Black); > - CRT_colors[MEMORY_BUFFERS] = ColorPair(Blue,Black); > + CRT_colors[MEMORY_DIRTY] = ColorPair(Blue,Black); > CRT_colors[MEMORY_CACHE] = ColorPair(Yellow,Black); > CRT_colors[LOAD_AVERAGE_FIFTEEN] = A_BOLD | ColorPair(Black,Black); > CRT_colors[LOAD_AVERAGE_FIVE] = A_NORMAL; > diff --git a/CRT.h b/CRT.h > index f7d4d72..22125e2 100644 > --- a/CRT.h > +++ b/CRT.h > @@ -75,7 +75,7 @@ typedef enum ColorElements_ { > GRAPH_8, > GRAPH_9, > MEMORY_USED, > - MEMORY_BUFFERS, > + MEMORY_DIRTY, > MEMORY_CACHE, > LOAD, > LOAD_AVERAGE_FIFTEEN, > diff --git a/MemoryMeter.c b/MemoryMeter.c > index eca0442..0f59808 100644 > --- a/MemoryMeter.c > +++ b/MemoryMeter.c > @@ -22,17 +22,18 @@ in the source distribution for its full text. > }*/ > > int MemoryMeter_attributes[] = { > - MEMORY_USED, MEMORY_BUFFERS, MEMORY_CACHE > + MEMORY_USED, MEMORY_DIRTY, MEMORY_CACHE > }; > > static void MemoryMeter_setValues(Meter* this, char* buffer, int size) { > long int usedMem = this->pl->usedMem; > - long int buffersMem = this->pl->buffersMem; > - long int cachedMem = this->pl->cachedMem; > - usedMem -= buffersMem + cachedMem; > + long int dirtyMem = this->pl->dirtyMem + this->pl->writebackMem; > + long int cachedMem = this->pl->buffersMem + this->pl->cachedMem; > + usedMem -= cachedMem; > + cachedMem -= dirtyMem; > this->total = this->pl->totalMem; > this->values[0] = usedMem; > - this->values[1] = buffersMem; > + this->values[1] = dirtyMem; > this->values[2] = cachedMem; > snprintf(buffer, size, "%ld/%ldMB", (long int) usedMem / 1024, (long int) this->total / 1024); > } > @@ -43,7 +44,7 @@ static void MemoryMeter_display(Object* cast, RichString* out) { > int k = 1024; const char* format = "%ldM "; > long int totalMem = this->total / k; > long int usedMem = this->values[0] / k; > - long int buffersMem = this->values[1] / k; > + long int dirtyMem = this->values[1] / k; > long int cachedMem = this->values[2] / k; > RichString_write(out, CRT_colors[METER_TEXT], ":"); > sprintf(buffer, format, totalMem); > @@ -51,9 +52,9 @@ static void MemoryMeter_display(Object* cast, RichString* out) { > sprintf(buffer, format, usedMem); > RichString_append(out, CRT_colors[METER_TEXT], "used:"); > RichString_append(out, CRT_colors[MEMORY_USED], buffer); > - sprintf(buffer, format, buffersMem); > - RichString_append(out, CRT_colors[METER_TEXT], "buffers:"); > - RichString_append(out, CRT_colors[MEMORY_BUFFERS], buffer); > + sprintf(buffer, format, dirtyMem); > + RichString_append(out, CRT_colors[METER_TEXT], "dirty:"); > + RichString_append(out, CRT_colors[MEMORY_DIRTY], buffer); > sprintf(buffer, format, cachedMem); > RichString_append(out, CRT_colors[METER_TEXT], "cache:"); > RichString_append(out, CRT_colors[MEMORY_CACHE], buffer); > diff --git a/ProcessList.c b/ProcessList.c > index 99a6512..94a9a5e 100644 > --- a/ProcessList.c > +++ b/ProcessList.c > @@ -127,6 +127,8 @@ typedef struct ProcessList_ { > unsigned long long int sharedMem; > unsigned long long int buffersMem; > unsigned long long int cachedMem; > + unsigned long long int dirtyMem; > + unsigned long long int writebackMem; > unsigned long long int totalSwap; > unsigned long long int usedSwap; > unsigned long long int freeSwap; > @@ -788,6 +790,14 @@ void ProcessList_scan(ProcessList* this) { > if (String_startsWith(buffer, "Cached:")) > sscanf(buffer, "Cached: %llu kB", &this->cachedMem); > break; > + case 'D': > + if (String_startsWith(buffer, "Dirty:")) > + sscanf(buffer, "Dirty: %llu kB", &this->dirtyMem); > + break; > + case 'W': > + if (String_startsWith(buffer, "Writeback:")) > + sscanf(buffer, "Writeback: %llu kB", &this->writebackMem); > + break; > case 'S': > if (String_startsWith(buffer, "SwapTotal:")) > sscanf(buffer, "SwapTotal: %llu kB", &this->totalSwap); > diff --git a/ProcessList.h b/ProcessList.h > index e410ae2..cdc4c4e 100644 > --- a/ProcessList.h > +++ b/ProcessList.h > @@ -110,6 +110,8 @@ typedef struct ProcessList_ { > unsigned long long int sharedMem; > unsigned long long int buffersMem; > unsigned long long int cachedMem; > + unsigned long long int dirtyMem; > + unsigned long long int writebackMem; > unsigned long long int totalSwap; > unsigned long long int usedSwap; > unsigned long long int freeSwap; > diff --git a/htop.c b/htop.c > index cdee8ee..220aa8e 100644 > --- a/htop.c > +++ b/htop.c > @@ -102,7 +102,7 @@ static void showHelp(ProcessList* pl) { > mvaddstr(4, 0, "Memory bar: "); > addattrstr(CRT_colors[BAR_BORDER], "["); > addattrstr(CRT_colors[MEMORY_USED], "used"); addstr("/"); > - addattrstr(CRT_colors[MEMORY_BUFFERS], "buffers"); addstr("/"); > + addattrstr(CRT_colors[MEMORY_DIRTY], "dirty"); addstr("/"); > addattrstr(CRT_colors[MEMORY_CACHE], "cache"); > addattrstr(CRT_colors[BAR_SHADOW], " used/total"); > addattrstr(CRT_colors[BAR_BORDER], "]"); |
From: Seth <ht...@se...> - 2013-02-06 14:12:21
|
On 02/06/2013 02:53 PM, Seth wrote: > [...] might have a user for this. sic -- s/user/use/ > On my workstation, and under the most extreme of loads I could think of, > the most I've seen reported 'Dirty" is 11MiB. (Note that it is usually solid 0M 90% of the time) |
From: Richard B. <rb...@sc...> - 2013-02-06 14:41:20
|
On Wed, Feb 06, 2013 at 03:12:13PM +0100, Seth wrote: > > On my workstation, and under the most extreme of loads I could think of, > > the most I've seen reported 'Dirty" is 11MiB. > (Note that it is usually solid 0M 90% of the time) That's expected, and that's why I mentioned it's mostly useful for system administrators and advanced users. The Linux kernel, and in particular some recent versions, strongly limit the maximum dirty memory [1]. Tuning vm.dirty_background_ratio and vm.dirty_ratio is the most common way to optimize systems with high I/O load. For example, try setting them to respectively 25 and 75, do something that generates many I/O requests, such as unpacking a large archive (e.g. a linux tarball), and observe it on htop. You should also note that the rest of your system should be smoother than with the defaults (depending on your version; 2.6.38 already adds a lot in that regard, but older kernels may simply block hard on I/Os until they're finished). You should now see how users who care about memory and I/O can find it very useful. Compare that with the current separation of buffers and cache. A lot of users just don't understand what the difference between buffers and cache is, and can't make any useful decision based on that. I personally don't get the point of statistics that don't help understanding the work load and how to improve it. In addition, the default life time of dirty pages in the kernel is 30 seconds, which isn't that volatile. Think of a database server highly loaded with I/O requests, the meter will just never be 0. -- Richard Braun [1] http://www.gossamer-threads.com/lists/linux/kernel/1017204 |
From: Seth <ht...@se...> - 2013-02-06 14:48:52
|
Thanks for the background. I'll look into it some more with different loads and tunings. On 02/06/2013 03:41 PM, Richard Braun wrote: > On Wed, Feb 06, 2013 at 03:12:13PM +0100, Seth wrote: >>> On my workstation, and under the most extreme of loads I could think of, >>> the most I've seen reported 'Dirty" is 11MiB. >> (Note that it is usually solid 0M 90% of the time) > That's expected, and that's why I mentioned it's mostly useful for > system administrators and advanced users. The Linux kernel, and in > particular some recent versions, strongly limit the maximum dirty > memory [1]. Tuning vm.dirty_background_ratio and vm.dirty_ratio is the > most common way to optimize systems with high I/O load. > > For example, try setting them to respectively 25 and 75, do something > that generates many I/O requests, such as unpacking a large archive > (e.g. a linux tarball), and observe it on htop. You should also note > that the rest of your system should be smoother than with the defaults > (depending on your version; 2.6.38 already adds a lot in that regard, > but older kernels may simply block hard on I/Os until they're finished). > > You should now see how users who care about memory and I/O can find it > very useful. Compare that with the current separation of buffers and > cache. A lot of users just don't understand what the difference between > buffers and cache is, and can't make any useful decision based on that. > I personally don't get the point of statistics that don't help > understanding the work load and how to improve it. In addition, the > default life time of dirty pages in the kernel is 30 seconds, which > isn't that volatile. Think of a database server highly loaded with I/O > requests, the meter will just never be 0. > |
From: Richard B. <rb...@sc...> - 2013-03-10 11:50:09
|
On Wed, Jan 30, 2013 at 09:13:42PM -0200, Hisham wrote: > Seth and everyone else reading this, all feedback regarding the > behavior and usefulness of this patch is extremely welcome. This is a > major UI change if we adopt this, so I need to be sure it's for the > best (I'll most likely use it myself for a while to try it out when I > get around to test it.) Any news about this change ? -- Richard Braun |
From: Seth <ht...@se...> - 2013-03-10 12:18:14
|
On 03/10/2013 12:30 PM, Richard Braun wrote: > Any news about this change ? Yeah, I'm still running with the patch. I must say I don't find it generally useful enough to warrant replacing the cached/buffer distinction with. I'm all in favour of a patch that allows an option (like under F2 "Setup"/"Meters"/"Memory Bar", e.g. "Memory Detail" or "Memory Breakdown"). Since my last report/query I have seen a case where 'dirty' pages reported was significant (>10miB). I think that was while `pvmove`-ing LVM2 physical volumes from one SSD to another, live. And another time while copying virtual machines. However, like I said before, the output of `vmstat`, `iotop` is more useful to me (also, it can be logged and graphed for multiple servers). If the figure is really that meaningful to anyone else, I'd expect a log/graph with peak values to be much more interesting, as this is very volatile information, and IME sysadmins can't monitor all their systems visually 24/7. I like the fact that cache/buffer is normally shown, as (a) it reminds people how block, dentry and inode cache work (b) it shows me whether my system's memory is being utilized. Remember we're not all sys-adminning virtual server hosts. At the htop devs: I'm just reporting from the field, feel free to opt whichever way you deem best (you probably talk to a lot more endusers than I do, and I might be blind to a few usecases :)) Cheers, Seth |
From: Hisham <h...@hi...> - 2013-03-11 16:50:44
|
On 10 March 2013 09:18, Seth <ht...@se...> wrote: > At the htop devs: I'm just reporting from the field, feel free to opt > whichever way you deem best (you probably talk to a lot more endusers > than I do, and I might be blind to a few usecases :)) To be honest, I don't get that much feedback from end-users, really, other than the occasional thank-you (thanks!) or bug report. My own use case is pretty pedestrian -- I used to access a few servers and VMs in my previous job but nowadays I mostly manage desktop machines only. You guys have raised interesting questions, though, so I can see the relative values of reporting this data. What I'll probably do is to make this optional, and leave the default behavior as the one people are used to. Thank you for all the feedback! -- Hisham http://hisham.hm/ |
From: Richard B. <rb...@sc...> - 2013-03-10 13:35:10
|
On Sun, Mar 10, 2013 at 01:18:05PM +0100, Seth wrote: > I like the fact that cache/buffer is normally shown, as (a) it reminds > people how block, dentry and inode cache work (b) it shows me whether my > system's memory is being utilized. > > Remember we're not all sys-adminning virtual server hosts. Well, you don't have to be a sysadmin to find it useful. As you put it, they generally use other, more detailed tools with reports over time. What I really find useful about the patch, as a user (ok, a power-user, but people caring about either buffers/cache or dirty/clean all are), is that I can test a use case and see a live, global state of the system in a small corner of the window at the same time. It can help, e.g. noticing some linking operations take a lot of memory in a build process, or tune a virtual machine by giving it less memory and making it rely on the host cache instead. When my user interface suddenly starts to freeze, I can readily know if it comes from writebacks or something else. Now, I agree a figure in the 10M is really low. And that's a concern. I think it comes from the strong limit put on the dirty memory limits, but it may also be caused by internal LVM operations, I don't know. What I know is that, with the tuning I did on my machines, It's not rare to have several hundreds MB (even thousands on rare occasions) of dirty memory (e.g. when creating file system images for some embedded devices. While some people might argue that it's insane to have such amounts of dirty memory, if either the data isn't that significant (i.e. you can recover it easily or it's simply volatile), or if you rely on your hardware to be fault tolerant (no unnotified power cut), and your working set fits in the page cache, it just boosts performance a lot. About the fact that it's volatile, again, I have to disagree. It's just as volatile as cpu usage, number of tasks or load average, which are what top/htop already show. And the default lifetime of 30 seconds means that one of the main use cases (machine gets slow, let's start htop and see what's happening) can perfectly report the values in a useful way. Also, showing buffers/cache doesn't say anything about dentry and inode caches... The patch merely merges the buffers and file cache into a dirty/clean unified page cache. The sum of buffers+cache should be the same as dirty+cache, so it continues to show whether memory is being used. What do others think about it ? -- Richard Braun |
From: Seth <ht...@se...> - 2013-03-10 13:57:26
|
On 03/10/2013 02:35 PM, Richard Braun wrote: > It can help, e.g. > noticing some linking operations take a lot of memory in a build > process, I'd just look at the working set/vmsize for that (usually, just pressing 'M' vs. 'P' in top) > or tune a virtual machine by giving it less memory and making > it rely on the host cache instead Do you run with swap? I haven't configured any of my machines with swap for at least .. many years now[*]. That might be a key difference in our setups. Whenever I want to make stuff faster, I just give it tmpfs to use. Which is a lot of the time. I usually work with everything (source code trees, even virtual machine images on tmpfs). Then whenever I created something I want to keep I "commit" it (either to a repository or by copying to persistent storage). I was a little sketchy on the caching things I mentioned. I should have said I'm used to seeing cache/buffer distinctively. It's probably as simple as that. I too am curious what other people think about the patch. Seth [*] I'm sure you know the reasoning. Just in case: To me, if swap is needed, you're already dead in the water.(It means the machine is underdimensioned for what it's supposed to do). I prefer to OOM-kill, rather than have swap grind the system to a halt |
From: Richard B. <rb...@sc...> - 2013-03-10 14:10:36
|
On Sun, Mar 10, 2013 at 02:57:16PM +0100, Seth wrote: > I'd just look at the working set/vmsize for that (usually, just pressing > 'M' vs. 'P' in top) You wouldn't know how much of it would be written back. > Do you run with swap? I haven't configured any of my machines with swap > for at least .. many years now[*]. That might be a key difference in our > setups. Yes but that's not the point, I only use swap as a backing store for unused anonymous memory. Let's simply say my guest systems don't support memory ballooning. > Whenever I want to make stuff faster, I just give it tmpfs to use. Which > is a lot of the time. I usually work with everything (source code trees, > even virtual machine images on tmpfs). Then whenever I created something > I want to keep I "commit" it (either to a repository or by copying to > persistent storage). My current build trees are too large to fit in memory. I use ccache, and tuning virtual memory helps a lot when rebuilding parts of a build tree (which is my common working set, and not easily put in a tmpfs without the rest of the tree). This is actually what made me think about patching htop. > I was a little sketchy on the caching things I mentioned. I should have > said I'm used to seeing cache/buffer distinctively. It's probably as > simple as that. That's very understandable. -- Richard Braun |
From: Seth <ht...@se...> - 2013-03-10 15:17:06
|
On 03/10/2013 03:10 PM, Richard Braun wrote: > My current build trees are too large to fit in memory. I use ccache, and > tuning virtual memory helps a lot when rebuilding parts of a build tree > (which is my common working set, and not easily put in a tmpfs without > the rest of the tree). This is actually what made me think about > patching htop. whoa. I'm unsure what to think. Impressive, I guess. I usually just clone my whole repository to /tmp before I start working. I'd have to be extremely greedy to run out of memory. On my smallest system, I'd have 4GB. I can "almost" imagine running out of space there if I included all of clang, gcc and boost there. ccache goes on tmpfs any way for me Just this morning I copied a virtual machine into my tmpfs for playing around. My main workstation has 32GB so that's not hard to do. And it performs :) With or without ballooning. Anyways, I'll leave it at this, because it's not really relevant, I'll leave the topic to others :) Seth |
From: Richard B. <rb...@sc...> - 2013-03-11 10:07:36
|
On Sun, Mar 10, 2013 at 04:16:52PM +0100, Seth wrote: > Anyways, I'll leave it at this, because it's not really relevant, I'll > leave the topic to others :) Well, it's relevant in so far as people who use tmpfs have little dirty memory, so that explains your numbers, and many people still don't have machines with 32 GB of RAM and rely on slow disks even for volatile storage. -- Richard Braun |