Thanks for the input Jan! 

When running the following exact code, I saw 20% %CPU in top as well, 
measured on a single socket E5-2696v4 server without any vm/container/CPU 
intensive task.  

package main

import (
  "time"
)

func main() {
  ticker := time.NewTicker(time.Millisecond)
  defer ticker.Stop()
  for range ticker.C {
  }
}

The following C++ program is the one I mentioned, I saw ~1% %CPU in top - 

#include <chrono>
#include <thread>

int main(int argc, char **argv, char **env)
{
  while(true)
  {
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
  }
}

> If you're observing 10% CPU usage, it means the scheduler does its job in 
about 100 microseconds. Maybe it can be improved but it does not look like 
suspiciously too much to me - considering what's happening behind the 
scenes.

I saw 20% %CPU usage in top when using time.Ticker, and > 10% when using 
time.Sleep(). This causes two real issues - 

1. users of my system keep asking me why an idle server process is still 
taking 20% %CPU every time when they look at top.
2. the system can't scale well when running in its simulation mode. In such 
simulation mode, I'd be running many instances of the same program on a 
multi-core machine each with a slightly different set of inputs (including 
many SIGKILL) for testing purposes. If each process is spending 20% %CPU by 
just having a ticker loop, it ends up wasting a significant portion of 
total CPU resources which could have been spent on more process instances 
for more tests.

Also interesting to know the standard of your mentioned "suspiciously too 
much" - how much is too much? To me, it is an obvious performance issue in 
Go's runtime. To further illustrate the problem, I've come up with another 
program showing that if I move the ticker/sleep part to C and let the C 
code to call my periodic task in Go every 1 millisecond, the %CPU is 
dramatically reduced to 2-3%. I believe this is not the kind of cgo 
"optimization" users should be doing on their own. 



ticker.h
----------

#ifndef TEST_TICKER_H
#define TEST_TICKER_H

void cticker();

#endif // TEST_TICKER_H


ticker.c
----------

#include <unistd.h>
#include "ticker.h"
#include "_cgo_export.h"

void cticker()
{
  for(int i = 0; i < 30000; i++)
  {
    usleep(1000);
    Gotask();
  }
}


ticker.go
-----------

package main

/*
#include "ticker.h"
*/
import "C"
import (
  "log"
)

var (
  counter uint64 = 0
)

//export Gotask
func Gotask() {
  counter++
}

func main() {
  C.cticker()
  log.Printf("Gotask called %d times", counter)
}


  

On Sunday, September 16, 2018 at 5:10:07 PM UTC+8, Jan Mercl wrote:
>
> On Sun, Sep 16, 2018 at 10:49 AM Lei Ni <nil...@gmail.com <javascript:>> 
> wrote:
> func main() {
>         ...
>         for {
>                 select {
>                 case <-ticker.C:
>                         // call my function here
>                 }
>         }
> }
>
> Is the above the actual code you're using for the CPU usage "benchmark"? 
> If so, make the loop
>
> for range <-ticker.C  {
>         // call my function here
> }
>
> instead.
>
> > As comparison, the same can be done in C++ with about 1% %CPU in top. 
>
> Please show the C++ code to let others know what is meant by "the same", 
> thanks. My guess is that the C++ code only yields the thread to the kernel 
> which is indeed cheaper than rescheduling goroutines in a Go program when 
> one of them blocks or sleeps. If you're observing 10% CPU usage, it means 
> the scheduler does its job in about 100 microseconds. Maybe it can be 
> improved but it does not look like suspiciously too much to me - 
> considering what's happening behind the scenes.
>
> FTR, a 1 msec ticker will make something called 1000 times in a second on 
> a common system only when almost idle otherwise. IIRC, for example Linux 
> schedules threads on a 100 msec base by default.
>
> -- 
>
> -j
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to