-
-
Notifications
You must be signed in to change notification settings - Fork 424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unhardcode tick-to-ms conversion #381
Conversation
darwin/DarwinProcess.c
Outdated
@@ -240,6 +240,12 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, | |||
proc->updated = true; | |||
} | |||
|
|||
double ticks_to_nanoseconds(const double ticks) { | |||
const double secs_per_tick = 1.0 / (double)sysconf(_SC_CLK_TCK); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably best to cache the results of this sysconf call so that we're not recalculating it on every sample? (perhaps a global 'hertz' var set from either the darwin Platform_init or ProcessList_new routine)
sysconf can also fail, so doing this call once on startup will make error checking / handling easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! Though I'm not a fan of herz
, I'd rather something like clock_ticks_per_s
. Thoughts?
I just feeling out if this PR is a move in the right direction.
I noticed that a lot of this code-base is unclear about units, exact derivations, etc., so I'm not sure if this kind of change would be desired or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! Though I'm not a fan of
herz
, I'd rather something likeclock_ticks_per_s
. Thoughts?
Sure, doesn't have to be hertz - if its multi-words like that though camel case is more commonly used in htop (see darwin/Platform.c for some examples).
I just feeling out if this PR is a move in the right direction.
Looks like its moving in a less broken direction - so two thumbs up from me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, I didn't notice. Looks like local vars are snake case, and functions/types are camel case. I'll change my identifiers to match.
Some other questions:
-
Should I add an explicit but technically redundant
#include <unistd.h>
? It's what definessysconf
, but it's also already indirectly included (probably by CoreFoundation, but I haven't checked. -
The return type of
sysconf
islong
. Should the cache variable match that and be along
, or useuint64_t
like the rest? Or should I cache it after conversion todouble
? -
I saw that
sysconf(_SC_CLK_TCK)
is also called inLinuxProcess_adjustTime
. They called the cache varjiffy
. It appears that they use a lazy-initialization pattern, that makessysconf(_SC_CLK_TCK)
called upon the first call toLinuxProcess_adjustTime
.They fail silently if the
errno
is set, by just assuming 100 Hz. That seems... like the wrong choice to me. Wouldn't it be better to fail loudly than to assume a potentially wrong value? I feel like I'm pulling a thread here haha.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1. Should I add an explicit but technically redundant `#include <unistd.h>`? It's what defines `sysconf`, but it's also already indirectly included (probably by CoreFoundation, but I haven't checked.
I'd not add it explicitly unless its needed to compile - as you say, chances are its included indirectly already.
2. The return type of `sysconf` is `long`. Should the cache variable match that and be a `long`, or use `uint64_t` like the rest? Or should I cache it after conversion to `double`?
I recommend you do as much work up front as possible, at startup, and as little work as possible during each sample.
Thus, I think its best to store it as a double (like you had it in the original patch).
3. I saw that `sysconf(_SC_CLK_TCK)` is also called in `LinuxProcess_adjustTime`. They called the cache var `jiffy`. It appears that they use a lazy-initialization pattern, that makes `sysconf(_SC_CLK_TCK)` called upon the first call to `LinuxProcess_adjustTime`.
There's a good chance this code can be improved also.
They fail silently if the `errno` is set, by just assuming 100 Hz. That seems... like the wrong choice to me. Wouldn't it be better to fail loudly than to assume a potentially wrong value? I feel like I'm pulling a thread here haha.
Heh - yep. It definitely would be better to fail htop at startup if this call fails - on Linux too, IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I recommend you do as much work up front as possible, at startup, and as little work as possible during each sample.
Thus, I think its best to store it as a double (like you had it in the original patch).
I had a change of mind on this. Though double
suits my usecase, some other feature might end up re-using it and converting it to uint64_t
, so I was leaning towards keeping it as its original long
. It's just one cvttsd2si
instruction, and the compiler could probably lift the conversion of out of the loop anyway.
Heh - yep. It definitely would be better to fail htop at startup if this call fails - on Linux too, IMO.
Opened #384 to track this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@natoscott NVM, the style guide suggests to add such headers: https://github.com/htop-dev/htop/blob/master/docs/styleguide.md#import-and-use-of-headers
d5fbf7a
to
e830ea1
Compare
Might help resolve #368 … |
e830ea1
to
0adfecb
Compare
13945a1
to
b5c13dd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if all the explicit double
casts are technically required.
darwin/Platform.h
Outdated
@@ -31,6 +31,8 @@ extern const unsigned int Platform_numberOfSignals; | |||
|
|||
extern const MeterClass* const Platform_meterTypes[]; | |||
|
|||
extern long Platform_clockTicksPerSec; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably something for another PR, but if multiple platforms have this (Darwin + Linux, but basically *BSD too), this should most likely go into a global platform header (cf. #306) for some central interface for such universally needed information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. See also: #384
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment was mostly about this declaration itself, which is probably better suited to have in some platform-independent header and not with every platform.
That's different from #384, but could easily be resolved there.
dcb4a07
to
5d84b87
Compare
darwin/DarwinProcess.c
Outdated
@@ -6,6 +6,7 @@ in the source distribution for its full text. | |||
*/ | |||
|
|||
#include "DarwinProcess.h" | |||
#include "Platform.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cf. styleguide on include order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I got it right this time, let me know.
darwin/DarwinProcess.c
Outdated
/ ((double)dpl->global_diff * 100000.0); | ||
double time_interval = ticksToNanoseconds(dpl->global_diff) / (double) dpl->super.cpuCount; | ||
|
||
proc->super.percent_cpu = ((double)diff / time_interval) * 100.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should include some check for time_interval
to not be too small. Epsilon check for interval > 1e-6
should be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the meaning if interval is so small? Two back-to-back updates were done in very short succession?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5d84b87
to
dccca07
Compare
dccca07
to
27a3afc
Compare
I rebased you PR onto #392 to include the changes from there. |
@@ -240,23 +241,28 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, | |||
proc->updated = true; | |||
} | |||
|
|||
static double ticksToNanoseconds(const double ticks) { | |||
const double nanos_per_sec = 1e9; | |||
return ticks / (double) Platform_clockTicksPerSec * Platform_timebaseToNS * nanos_per_sec; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Platform_clockTicksPerSec * Platform_timebaseToNS * nanos_per_sec
is a runtime constant.
Maybe pre-compute it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean something like?
static const double tickToNanosecondsScale = (double) Platform_clockTicksPerSec * Platform_timebaseToNS * 1e9;
return ticks / tickToNanosecondsScale;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would not work, as static
variables are initialized before main()
(and Platform_clockTicksPerSec
and Platform_timebaseToNS
are not yet set at this point).
Maybe it's OK to compute once every cycle when caching time_interval
(see below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
k, had to recheck on the actual initialization semantics here. Would take a second (bool
) variable to act as lazy initialization guard to calculate this constant on first entry.
But as both values are set in Platform_init
we can just initialize that scaling factor there.
if (0 != proc->utime || 0 != proc->stime) { | ||
uint64_t diff = (pti.pti_total_system - proc->stime) | ||
+ (pti.pti_total_user - proc->utime); | ||
double time_interval = ticksToNanoseconds(dpl->global_diff) / (double) dpl->super.cpuCount; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
double time_interval = ticksToNanoseconds(dpl->global_diff) / (double) dpl->super.cpuCount;
is constant for all processes of a single update cycle.
Maybe pre-compute it in DarwinProcessList.c::ProcessList_goThroughEntries()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then this should be passed in as parameter to DarwinProcess_setFromLibprocPidinfo
to avoid depending on global state.
Division by 100000.0 worked because `sysconf(_SC_CLK_TCK)` happened to be 100. By unhardcoding: 1) It becomes more clear what this 100000.0 figure comes from. 2) It protects against bugs in the case `sysconf(_SC_CLK_TCK)` ever changes.
27a3afc
to
56557fc
Compare
Applied via 67ccd6b Thanks for the contribution! |
Division by 100000.0 worked because
sysconf(_SC_CLK_TCK)
happened to be 100.By unhardcoding:
10000.0
figure comes from.sysconf(_SC_CLK_TCK)
ever changes.