-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Prepopulating a Process struct with a set of fields #286
Comments
Sorry for late response. You are right. current approach is wasteful if user want to read information from same file.
Do you have any idea? |
Hi, I can think of several ways. Add a new Regarding invalidation, I think it's fine if we let the user control it. Alternatively, we can say that this way of creating a Process makes it immutable and it will not refresh data after construction. I'd like gopsutil to have reasonable performance when getting information for a set of pids & predefined fields. If you think of how it works now, take darwin for example, for N pids we're making N calls to ps just to get a single field. If I have M fields, that's N*M calls to ps, which is very slow. If we're calling an API to get a piece of information (whether it is a shell command like ps, or a library call), we should get all the information we can so the cost of getting those M fields is as low as possible. |
How about add Cache can be used for other platform. So ps problem you told can be solved, I think. What do you think? |
Sounds like a good start. Can we also support the zero time.Duration so a user must call CacheInvalidate to get new values? This should avoid the need to check the current time on every call to get the value of something. |
Passing So, I am thinking about introduce new two fields.
How do you think? (edited: add individual cached time and value into to the |
It might be prettier to use negative duration as "cache disabled". So:
|
Have you had a chance to make progress with this? If not I might take a crack at it this weekend. |
I'm sorry for late response. I agree your "negative duration" idea. I will very appreciate if you make a PR. |
Hi there and thx for all the work on this badly needed library. Indeed, if you want to use this lib to get information about a lot of processes and/or fields the performance is quite relevant.
That way the lib getters (public or internal) only have to compare their cache stamp with the current stamp and invalidate their cache accordingly. No time.Now(), no complex cache invalidation scheme. When you call a getter you fill all the fields you come upon (during the various /proc/pid/* or ps) while looking for the required values. Next calls to other getters will find those values cached until the stamp changes. |
I'm also interested in this feature. As I do something like:
We means fillFromStatusWithContext is called twice and do twice the work :( FYI, Python's psutil use a context which enable caching until context is exited: https://psutil.readthedocs.io/en/latest/#psutil.Process.oneshot I think it a simple solution which avoid any issue with cache invalidation and it solve my use case (and author's use-case if I understand well). Biggest issue, go don't have such kind of context :) I'm willing to propose a PR to solve my use-case, be it either:
@shirou which solution do you want me to implement ? |
I prefer the solution in #286 (comment), with immutable information, to keep the API simple. It could be a drop-in replacement for the majority of use-cases. Something like type ProcessWithFields struct { // better name to be suggested? We could reuse the Process type and do some check to know if it's a snapshot process or not
Pid int32 `json:"pid"`
// [...] implem details
}
type Field uint
const (
Name Field = iota + 1
Exe
// [...]
)
func NewProcessWithFields(pid int32, fields ...Field) (*Process, error) {
// retrieve data cleverly
}
func ProcessesWithFields(fields ...Field) ([]*Process, error) {
// retrieve data cleverly for all processes
}
// same functions with WithContext
func (p *ProcessWithFields) Name() (string, error) {
return p.name nil
}
// same for the other fields Keep in mind this is a huge task and refactoring (to limit code duplication between current implementation and the "WithFields" one), as process data is not obtained the same way for all the OSes, the implementation and the "quick paths" will be platform-dependent. I'll be glad to assist you in all this. |
Ok seems indeed a good API. I'll start working on this way. |
When calling a function on a Process instance, it will go and get the most fresh information. If the pieces of information are all in the same file, that file will be read on each call. This is really wasteful if you know what you need upfront.
It would be nice if a Process could be created such that a set of fields are cached on initialization. Obviously if we're getting fields A, B and C from file F, we should only read F once.
It would be a lot easier to pull this off if Process was an interface rather than a struct.
The text was updated successfully, but these errors were encountered: