pamelafox / lscache

A localStorage-based memcache-inspired client-side caching library.
Other
1.46k stars 160 forks source link

Why use 2 keys for 1 value? #79

Open peter-gribanov opened 6 years ago

peter-gribanov commented 6 years ago

Why use 2 keys?

  1. key for store the value
  2. key for store the expiration time

Why don't use the structure?

{
    value: my_value,
    expire: timestamp,
}

I see several problems using two keys:

1. Nullable values #52

If you use a structure, you can know for sure that the value is in the cache even if it's empty.

2. Integrity of keys

One of the keys can be lost and the integrity of the data will be broken. The browser sometimes cleans localStorage. localStorage can be cleared by the user.

3. Speed of work

In the get() method, you twice access to the localStorage. I don't think that this has a positive effect on performance.

4. More space is required

Two keys take up more space than the structure.

For example:

lscache.set('greeting', 'Hello World!', 2);

This code makes two kays:

key value
lscache-greeting Hello World!
lscache-greeting-cacheexpiration 25259579612566

That is ~74 bytes.

If you use a structure, you get:

key value
lscache-greeting {value:'Hello World!',expire:25259579612566}

That is ~60 bytes.

If you use a bucket, the difference will be even greater.

lscache.setBucket('AcmeDemo-');
lscache.set('greeting', 'Hello World!', 2);
key value
lscache-AcmeDemo-greeting Hello World!
lscache-AcmeDemo-greeting-cacheexpiration 25259579612566
key value
lscache-AcmeDemo-greeting {value:'Hello World!',expire:25259579612566}

~92 bytes vs ~69 bytes

This difference can be further reduced if you change the storage structure to array:

[my_value, timestamp]
key value
lscache-AcmeDemo-greeting ['Hello World!',25259579612566]

~92 bytes vs ~56 bytes

This is almost a twofold saving. For someone, this can be meaningful.

In sum

Maybe i don't understand something, please explain.

PS: I can make PR for fix it.

pamelafox commented 6 years ago

Hm. Great points on the PROs, better performance and space. At this point, I can't recall why I went with 2 keys. I'd be a bit concerned about changing the underlying implementation in case of folks somehow relying on the 2-key storage. As I mentioned in another thread, I tend to be very cautious with PRs, since I'm not a current user myself and just maintain this in free time. I'd hate to introduce any breaking changes.

cantsdmr commented 6 years ago

lscache maybe should reach to 2.0 with these features without any breaking changes.

peter-gribanov commented 6 years ago

@cantsdmr need active support of the project in order to make a new major release. Pamela can't deal with the project.

I could admin project, but i still have a little experience with using this library.

cantsdmr commented 6 years ago

@peter-gribanov yes, I think you can manage a fork of lscache or 2.0 release.

rcky commented 6 years ago

@pamelafox @peter-gribanov I guess you wanted to prevent the cache from parsing the content at the specified key just to read the expiration time (which I think is relevant for large datasets).

peter-gribanov commented 6 years ago

@rcky We need to read the expiration time separately from the data only when the cache is out of date.

If we read data from the cache more often than flush it (must be), then it's more efficient to read the expiration time together with the data and not do unnecessary actions.

For optimization, we can opt out of JSON:

25259579612566|Hello World!

In order to know the expiration time, it is enough to read just a few first bytes and no longer spend time analyzing JSON.

rcky commented 6 years ago

@peter-gribanov I actually stumbled upon this discussion by chance. I don't doubt your argumentation, it just seemed to be the reasoning behind the current implementation.

But just out of curiosity:

We need to read the expiration time separately from the data only when the cache is out of date.

How do you know the cache is out of date without reading the expiration time (yeah reading it partially upfront seems legit)?

peter-gribanov commented 6 years ago

How do you know the cache is out of date without reading the expiration time? (yeah reading it partially upfront seems legit)?

@rcky i say

We need to read the expiration time separately from the data only when the cache is out of date.

We always need to read the expiration time, but don't always need to read the data. But, there are far fewer cases when we need to read the time without reading the data, so it's more economical to store them together.