Skip to content
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

compression of array and object values #109

Open
fippo opened this issue Jul 14, 2022 · 0 comments
Open

compression of array and object values #109

fippo opened this issue Jul 14, 2022 · 0 comments

Comments

@fippo
Copy link
Owner

fippo commented Jul 14, 2022

currently rtcstats makes the assumption that values are simple types like string or number.
There are two notable exceptions to this:

  • trackIds which is an array
  • qualityLimitationDurations which is an object

For arrays, they should not be transmitted again if they're deeply equal
For objects they should only transmit values that have changes. Unclear how to deal with values that get removed

The following snippet solves the array part which seems like the more important one:

const s1 = {
  foo: {
    trackIds: [ 'RTCMediaStreamTrack_sender_3' ],
    qualityLimitationDurations: {other:0, cpu:0, bandwidth: 2.93, none:0.073},
  },
};

const s2 = {
  foo: {
    trackIds: [ 'RTCMediaStreamTrack_sender_3', 'RTCMediaStreamTrack_sender_4' ],
    qualityLimitationDurations: {other:0, cpu:0, bandwidth: 2.93, none:0.073},
  },
};

const s3 = {
  foo: {
    trackIds: [ 'RTCMediaStreamTrack_sender_3', 'RTCMediaStreamTrack_sender_4' ],
    qualityLimitationDurations: {other:0, cpu:0, bandwidth: 3.00, bogus:0.073},
  },
};

const delta = {
  decompress: function(baseStats, newStats) {
    const timestamp = newStats.timestamp
    delete newStats.timestamp;
    Object.keys(newStats).forEach(id => {
      if (!baseStats[id]) {
        if (newStats[id].timestamp === 0) {
          newStats[id].timestamp = timestamp;
        }
        baseStats[id] = newStats[id];
      } else {
        const report = newStats[id];
        if (report.timestamp === 0) {
            report.timestamp = timestamp;
        } else if (!report.timestamp) {
            report.timestamp = new Date(baseStats[id].timestamp).getTime();
        }
        Object.keys(report).forEach(name => {
          baseStats[id][name] = report[name];
        });
      }
    });
    return baseStats;
  },
  compress: function(baseStats, newStats) {
    Object.keys(newStats).forEach(id => {
      if (!baseStats[id]) {
        return;
      }
      const report = newStats[id];
      Object.keys(report).forEach(name => {
        if (report[name] === baseStats[id][name]) {
          delete newStats[id][name];
        } else if (Array.isArray(report[name])) {
          // Arrays get serialized if anything changed.
          if (JSON.stringify(report[name]) === JSON.stringify(baseStats[id][name])) {
            delete newStats[id][name];
          }
        }
        delete report.timestamp;
        if (Object.keys(report).length === 0) {
          delete newStats[id];
        }
      });
    });
    // TODO: moving the timestamp to the top-level is not compression but...
    newStats.timestamp = new Date();
    return newStats;
  }
};

const c1 = delta.compress({}, s1);
const c2 = delta.compress(c1, s2);
// Should be an array with two objects since this is an array.
console.log('should not compress Array with newly added members (result: array with two)', c2['foo'].trackIds);
//console.log('should compress objects with the same values (result: undefined)', c2['foo'].qualityLimitationDurations);

const c3 = delta.compress(c2, s3);
console.log('should compress Array with same members (result: undefined)', c3['foo'].trackIds);
//console.log('should compress objects with different values (result: undefined)', c3['foo'].qualityLimitationDurations);

const u1 = delta.decompress({}, c1);
const u2 = delta.decompress(u1, c2);
console.log('should decompress Array with newly added members (result: array with two)', u2['foo'].trackIds);
//console.log('should decompress objects with same values (result: object with four values)', u2['foo'].qualityLimitationDurations);
const u3 = delta.decompress(u2, c3);
console.log('should decompress Array with old members (result: array with two)', u3['foo'].trackIds);

by adding an Array.isArray check which does a naive full-json comparison.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant