frostwire / frostwire-jlibtorrent

A swig Java interface for libtorrent by the makers of FrostWire. Develop libtorrent based apps with the joy of coding in Java.
http://www.frostwire.com
MIT License
451 stars 138 forks source link

[enhancement] TorrentStats #WIP #137

Closed gubatron closed 7 years ago

gubatron commented 7 years ago

After some conversations, we believe it will be of the benefit of all the jlibtorrent users to have a simple and memory efficient Stats Provider tool so that they can create things like download, upload, download + upload, and disk cache graphs on their BitTorrent clients or BitTorrent based back ends, to visually monitor performance.

This will also help us benchmark jlibtorrent's performance on every release if someone wants to help us write some benchmarking tests. :)

Goals

  1. TorrentStats should be an optional tool.
  2. TorrentStats should not break any existing jlibtorrent API.
  3. TorrentStats should be memory and CPU efficient.
  4. TorrentStats should be as less code intrusive to use as possible, ideally the user should not have to write any alert listeners.
  5. TorrentStats user cannot modify or tamper the stats. Therefore whenever stats are requested, the user gets a copy of the samples, or a subset of the samples if the user doesn't need all of it. This should allow the UI code to simply add the last samples missing to update itself.
  6. TorrentStats should be aware of the torrent status and save CPU by not doing anything if the torrent is paused or if it has been removed from the session.
  7. TorrentStats should be flexible and allow the user to track statistics to the extend of her needs. User should be able to specify the maximum amount of time to track, and also the interval of the samples taken per torrent tracked. e.g. Track the last 30 minutes, every 0.5 secs.

Non Goals

  1. Any Disk I/O.
  2. Serialization of this data, we just want this for live stats, not historical stats, anything more is out of the current scope.

Ideal API Proposal


long samplingIntervalInMs = 1000; // 1 second
long maxHistoryInMs = 10*60*1000; // 10 minutes

// The number of samples to keep will always be maxHistoryLength / samplingInterval
// in this case, we'd keep up to 600000/1000 -> 600 samples for each metric.

// This creates a new TorrentStatsKeeper instance and all the internal alert listeners necessary
TorrentStats stats = TorrentStats.track(sessionManager, torrentHandle, samplingIntervalInMs, maxHistoryInMs);

// gets all the available upload speed samples (bytes/sec), in this case that'd be <= 600 elements
int[] uploadSpeeds = stats.get(TorrentStats.Upload);

// gets the last 10 available download speed samples or less if less available
int[] last10DownloadSpeedSamples = stas.get(TorrentStats.Download, 10);

// TODO: DiskNumWrites, DiskNumReads, CacheNumWrites, CacheNumReads, BytesWritten, BytesRead. Not adding this yet as I'm having a hard time finding the API calls in jlibtorrent, they may have been taken out CC: @aldenml
aldenml commented 7 years ago

I think that similar to SessionStats, there should be a map inside SessionManager of sha1->TorrentStats. These could be updated in the same inner alerts loop.

I'm not sure of having a free TorrentStatsKeeper to be used outside, the only one we have that way is PiecesTracker and I would like to remove it.

gubatron commented 7 years ago

Ok, if you want it to be a part of SessionManager my API would then look something like this then:

long samplingIntervalInMs = 1000; // 1 second
long maxHistoryInMs = 10*60*1000; // 10 minutes

// The number of samples to keep will always be maxHistoryLength / samplingInterval
// in this case, we'd keep up to 600000/1000 -> 600 samples for each metric.

// This creates a new TorrentStatsKeeper instance and all the internal alert listeners necessary
TorrentStats stats = sessionManager.trackStats(torrentHandle, samplingIntervalInMs, maxHistoryInMs);

// gets all the available upload speed samples (bytes/sec), in this case that'd be <= 600 elements
int[] uploadSpeeds = stats.get(TorrentStats.Upload);

// gets the last 10 available download speed samples or less if less available
int[] last10DownloadSpeedSamples = stas.get(TorrentStats.Download, 10);

Then Inside I'd still use a similar component as I don't want to have more code than it is necessary inside SessionManager, which should then be (like you say) similar to SessionStats.

👍

gubatron commented 7 years ago

change of plans @haperlot

aldenml commented 7 years ago

seems like a good starting point, let's see how plays out not having a type for speed.

aldenml commented 7 years ago

To old to continue here, better in code, see https://github.com/frostwire/frostwire-jlibtorrent/commit/15db864dcd203f583d4fcf32758a6b20daee9fdd