0

Running the following code (modified from 1)

import tkinter as tk
import time
import os

class App():
    def __init__(self):
    self.root = tk.Tk()
    self.label = tk.Label(text="")
    self.label.pack()
    self.update_clock()
    self.root.mainloop()

def update_clock(self):
    now = time.strftime("%H:%M:%S")
    self.label.configure(text=now)
    print(now)
    print (os.times())
    self.root.after(1000, self.update_clock)

app=App()

slightly increases the CPU load over time. In the example below from 0.1 to 0.2 within 1 minute

17:15:49
nt.times_result(user=0.0780005, system=**0.1092007**, children_user=0.0, children_system=0.0, elapsed=0.0)

17:16:49
nt.times_result(user=0.0780005, system=**0.2184014**, children_user=0.0, children_system=0.0, elapsed=0.0)

On a long term this will stall everything.

How to overcome this behaviour?
Is there a better solution to display a clock within tkinter "forever"?

Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • That is interesting. I am seeing the same kind of slow growth on my end as well. – Mike - SMT Sep 21 '17 at 15:45
  • 2
    Are you sure that "on a long term this will stall everything"? Surely that assumes linear growth in CPU consumption, which is very likely not the case. – SneakyTurtle Sep 21 '17 at 15:47
  • Is this _really_ your code? The indentation of `update_clock` looks suspiciously incorrect. – Bryan Oakley Sep 21 '17 at 18:47
  • Increasing system time does not mean increased cpu load. It just means the system is executing tasks on behalf of python. For example when you call `time.strftime`. Every time you call this function the system time increases. – Stop harming Monica Sep 21 '17 at 20:50

1 Answers1

0

According the the documentation:

os.times()

Return a 5-tuple of floating point numbers indicating accumulated (processor or other) times, in seconds. The items are: user time, system time, children’s user time, children’s system time, and elapsed real time since a fixed point in the past, in that order. See the Unix manual page times(2) or the corresponding Windows Platform API documentation. On Windows, only the first two items are filled, the others are zero.

The 2nd floating point in the tuple is the system time and according to this page system time == clock_t tms_stime

The tms_stime field contains the CPU time spent in the system while executing tasks on behalf of the calling process.

According to the WIKI on System Time the value returned by python is measured in μs. 1 μs == One millionth of one second

So those numbers even though they are growing should never really effect system performance.

Also windows might be returning 1 ms or 100 ns values according to the WIKI. 1 ns == One billionth of one second 1 ms = One thousandth of one second. Also numbers that are too small to really make a difference.

UPDATE:

After some testing I can see that the increase in the system time per operation is happening for tkinter widgets being update. I did try both labels and entry fields. I did confirm that the values being displayed for system time is the amount of time taken to process the method. I tested printing os.times() only to see if the system time would have the same growth as with updating a label and it does not.

I will keep looking to see what I can find.

I would think that if the same amount of lines of code is being called on each loop of the function then the same amount of processing time should be recorded. Maybe with a slight variation due to system response time but I should not see a slow and consistent growth of this response time.

It seams to only be happening while updating a tkinter widget like Entry, Labeland Text. When I am just printing these values to the console the system time never goes up.

Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • @Bryan Oakley I am very interested in this question but finding documentation on the matter is proving unlikely to happen. Do you have any insight on this question? – Mike - SMT Sep 21 '17 at 18:00
  • There is no log or history that records updates to tkinter widgets. – Bryan Oakley Sep 21 '17 at 18:49
  • @BryanOakley well I have been unable to find any documentation that would explain the increasing processing time reported by `os.times()` when using `after()` to updated a label. So I was trying to think of possible reasons for said increases in processing time. Would you happen to know the reason for this behavior? Or maybe have a link to some documentation on the returned values of `os.times()` as I have not been able to find much on how its reading and returning the values of `system time` at the 2nd float of the tuple it returns. – Mike - SMT Sep 21 '17 at 18:55
  • Don't be so quick to assume it's tkinter. It could just as easily be a problem in `os.times()` or in your interepretation of the results. Tcl/tk -- the underlying technology of tkinter -- has been used in mission critical 24/7 applications. If there were an issue like this, it would have been found years or decades ago. Plus, you seem to be claiming the system time is going up -- that's perfectly normal because the CPU is actually doing something every time through the loop. Note: the system time is for the _process_ as a whole, not the _method_. – Bryan Oakley Sep 21 '17 at 19:08
  • @BryanOakley: I actually tested this with just printing `os.times()` and not updating a widget. The `system time` did not change like it was with updating widgets. I did also test several widgets. I am not able to reproduce the growth of the `system time` outside of tkinter or when not updating a widget. I didn't just assume it was tkinter I have been performing many test with different variables to try and find a some common behavior or something that could point me in the right direction. This is why I have asked you for some insight as I know you have extensive knowledge on tkinter. – Mike - SMT Sep 21 '17 at 19:14
  • @BryanOakley: Its not a huge deal as I have programs that run all day that use this method to update a clock in my apps and they don't seam to be any problems with them. It is something I would like to know the source of. – Mike - SMT Sep 21 '17 at 19:16
  • I don't know all your testing methods, but when you call `self.label.configure(...)` dozens of lines of code are being executed. – Bryan Oakley Sep 21 '17 at 19:16
  • @BryanOakley: for example. If I run `for i in range(100000): x = i, print(os.times()), self.root.after(100, self.my_function)` the resulting `system time` float in the tuple never changes. but when I perform `self.any_widget.config(text = 'os.times()` the resulting `system time` slowly grows. I have tried variations of this and and some other ideas but the only method so far I can see that is growing this `system_time` is the use of `after()` while repeating a label config update. Or even an entry field or text box as well. – Mike - SMT Sep 21 '17 at 19:22
  • `x=i` is vastly less computationally expensive than `self.label.configure(...)`, probably by a few orders of magnitude. You aren't comparing apples to apples. – Bryan Oakley Sep 21 '17 at 19:35
  • @BryanOakley I thought running x=i a hundred thousand times would compensate for the difference. But that is not the only things I have been testing. Like I said its not a big deal I am just very curious what is the cause of the growth. Its intriguing to me as I cant seam to find any documentation or other instances of this happening outside of updating a widget. – Mike - SMT Sep 21 '17 at 19:41