How does core triggers cleanup of expired sessions in database?
Configuring Garbage Collection
  
  When a session opens, PHP will call the gc handler randomly
  according to the probability set by session.gc_probability /
  session.gc_divisor. For example if these were set to 5/100
  respectively, it would mean a probability of 5%. Similarly, 3/4 would
  mean a 3 in 4 chance of being called, i.e. 75%.
  
  If the garbage collection handler is invoked, PHP will pass the value
  stored in the php.ini directive session.gc_maxlifetime. The
  meaning in this context is that any stored session that was saved more
  than gc_maxlifetime ago should be deleted. This allows one to expire
  records based on idle time.
  
  However, some operating systems (e.g. Debian) do their own session
  handling and set the session.gc_probability variable to 0 to stop
  PHP doing garbage collection. That's why Symfony now overwrites this
  value to 1.
  
  If you wish to use the original value set in your php.ini, add the
  following configuration:

# config/packages/framework.yaml
framework:
    session:
        gc_probability: null

  
  Source: Symphony's official docs on Configuring Sessions and Save Handlers


In Drupal this is seen in /sites/default/default.settings.php

/**
 * Some distributions of Linux (most notably Debian) ship their PHP
 * installations with garbage collection (gc) disabled. Since Drupal depends on
 * PHP's garbage collection for clearing sessions, ensure that garbage
 * collection occurs by using the most common settings.
 */
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 100);


Since the above "most common settings" is set to 1/100, Garbage Collection would run 1% of the time. 

Now, as per the code comment, I presume this does not get put into settings.php when it gets auto-generated if your distribution has one already set one in one of its files as I don't see this in my settings.php

You can also set this in services.yml as seen in this answer.



In Conclusion

Note that while Drupal is built on top of Symphony, it does not rely on Symphony for this. I just quoted their nice explanation from their documentation. 

We learned that PHP automatically calls this gc() method every session.gc_probability/session.gc_divisor % of the time and if you look at PHP docs on SessionHandler.


  SessionHandler is a special class that can be used to expose the
  current internal PHP session save handler by inheritance. There are
  seven methods which wrap the seven internal session save handler
  callbacks (open, close, read, write, destroy, gc and create_sid).
  
  Source: http://php.net/manual/en/class.sessionhandler.php


core/lib/Drupal/Core/Session/SessionHandler.php 

/**
 * Default session handler.
 */

class SessionHandler extends AbstractProxy implements \SessionHandlerInterface { ...

 /**
   * {@inheritdoc}
   */
  public function gc($lifetime) {
    // Be sure to adjust 'php_value session.gc_maxlifetime' to a large enough
    // value. For example, if you want user sessions to stay in your database
    // for three weeks before deleting them, you need to set gc_maxlifetime
    // to '1814400'. At that value, only after a user doesn't log in after
    // three weeks (1814400 seconds) will his/her session be removed.
    $this-&gt;connection-&gt;delete('sessions')
      -&gt;condition('timestamp', REQUEST_TIME - $lifetime, '&lt;')
      -&gt;execute();
    return TRUE;
  }