KDE Utils/kwallet/Benchmark

From KDE Community Wiki
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Summary

One of the main concerns users had with the wallet was that new entries weren't saved immediately (Bug #105752). Before actually getting to work and coding a workaround (appending new passwords to the file without reencrypting all of it or creating a second file where new passwords are appended) I benchmarked the existing encryption to check the actual overhead that would be incurred by saving to the kwl file as soon as passwords were entered.

Code

I used the following code for benchmarking. Please keep in mind:

  • keys and passwords generated using random data are probably longer than the entries you actually have in your wallet.
  • only syncing the wallet is benchmarked
  • due to hd caching (and a rather modest filesize), most of the time reported should be used encrypting the data.
#include <kaboutdata.h>
#include <kcomponentdata.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
#include <kwallet.h>
#include <QApplication>
#include <QTime>
#include <QFile>

#include "../backend/kwalletentry.h"
#include "../backend/kwalletbackend.h"

using namespace KWallet;

static int getRandomBlock(QByteArray& randBlock) {
  QFile devrand("/dev/urandom");
  if (devrand.open(QIODevice::ReadOnly)) {
    int rc = devrand.read(randBlock.data(), randBlock.size());
    if (rc != randBlock.size()) {
      return -3;              // not enough data read
    }
    return 0;
  }

  return -1;
}


int main(int argc, char **argv) {
  KAboutData aboutData("kwalletbench", 0, ki18n("kwalletbench"), "version");
  KComponentData componentData(&aboutData);
  QApplication app( argc, argv );

  Backend back("/tmp/benchmark.kwl", true);

  back.open("benchmark");
  back.createFolder("benchmark");
  back.setFolder("benchmark");

  for (int i = 0; i <= 100000; i+=100) {
    for (int j = 0; j < 100; ++j) {
      Entry entry;
      QByteArray key, value;
      key.resize(20);
      if (getRandomBlock(key) != 0) {
        kDebug(0) << "Error";
      }
      value.resize(50);
      if (getRandomBlock(value) != 0) {
        kDebug(0) << "Error";
      }
      entry.setType(Wallet::Password);
      entry.setKey(key);
      entry.setValue(value);
      back.writeEntry(&entry);
    }

    QTime _start = QTime::currentTime();
    back.sync("benchmark");
    QTime _end = QTime::currentTime();

    kDebug(0) << i << ";" << _start.msecsTo(_end);
  }

  back.close();

  return 0;
}

Results

I benchmarked on a Q6600. As the encrypting code is single-threaded, only one core (2.4GHz) is being used. Please bear in mind that I didn't bother to run the test several times as the results are pretty clear - unfortunately this makes some of the numbers seem a little weird.

  • DebugFull
    • 1 password: 16ms
    • 100 passwords: 15ms
    • 1000 passwords: 32ms
    • 5000 passwords: 107ms
    • 10000 passwords: 192ms
  • Release
    • 1 password: 8ms
    • 100 passwords: 5ms
    • 1000 passwords: 15ms
    • 5000 passwords: 25ms
    • 10000 passwords: 56ms

Discussion

I assume that your usual wallet will contain less than 1000 entries. Due to the fact that any workaround would have to encrypt at least 1 entry (~ 8ms) this workaround would save around 15ms - 8ms = 7ms. This is clearly insignificant. Big overhead for syncing the wallet seems to be a myth.