Skip to content

added bulk read support #42

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

Closed
wants to merge 8 commits into from
Closed

Conversation

matej21
Copy link
Contributor

@matej21 matej21 commented Apr 29, 2016

  • is fallback necessary ?
  • SQLiteStorage and NewMemcachedStorage: read methods internally use bulkRead. Is it ok? I think performance impact won't be serious.
  • non-scalar keys are not allowed in a bulkLoad - alternative would be serialize non-scalar keys. what do you think?

@matej21 matej21 force-pushed the feature/bulk_load branch from 5ee1b40 to c25b0c1 Compare April 29, 2016 13:42
* @param callable
* @return array
*/
public function bulkLoad(array $keys, $fallback = NULL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to have one fallback? Woulldn't make more sense to have fallback for each key? Or support both?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

key is passed as a first parameter to the fallback.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but then you can't easily reuse callback for load and bulkLoad.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So each time you call bulkLoad you will build an array of callbacks? that does not sound right.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if you want e.g. three values whose value are calculated in a different way? You would have to build this logic by if/switch branching inside the callback. That feels a bit ugly...

Copy link
Contributor

@enumag enumag Apr 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @matej21.

@Majkl578 How about this?

public static function createCallbackSwitcher(array $callbacks)
{
    return function ($key, ...$args) use ($callbacks) {
        return $callbacks[$key](...$args);
    };
}

$cache->bulkLoad($keys, self::createCallbackSwitcher($callbacks));

@Majkl578
Copy link
Contributor

I don't think bulk reuse for single operation is a good idea, for performance reasons.

throw new Nette\InvalidArgumentException('Only scalar keys are allowed in a bulkLoad method.');
}
}
$keys = array_combine(array_map([$this, 'generateKey'], $keys), $keys);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replaces whole line with

$storageKeys = array_map([$this, 'generateKey'], $keys);

@Majkl578
Copy link
Contributor

Majkl578 commented Apr 29, 2016

Have you seen how doctrine/cache handles this? https://github.com/doctrine/cache/blob/master/lib/Doctrine/Common/Cache/CacheProvider.php
I like that approach more, they implement both, but for drivers that don't support multi-get, they fall back to serial fetch.

* @param string key
* @return array key => value pairs, missing items are omitted
*/
function bulkRead(array $keys);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: consider returning [$value1, $value2] instead of more complex [$key1 => $value1, $key2 => $value2]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storage would have to maintain the item order and check for missing values. This is easier.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but the implementation in Cache would be simpler and faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes but the same logic would have to be in the storage itself.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would depend on the storage. Now you assume that no storage can implement this efficiently.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I do assume that. Or do you know any storage that doesn't need that logic?

@JanTvrdik
Copy link
Contributor

The ideas is awesome, but the implementation needs a lot polishing.

require __DIR__ . '/Cache.php';

//storage without bulk load support
test(function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think dg uses test(function () { // storage without bulk load support pattern

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not matter :-)

@matej21
Copy link
Contributor Author

matej21 commented Apr 29, 2016

btw, the performance impact of bulkRead reuse for a single read is about 10-20%

}
}
$storageKeys = array_map([$this, 'generateKey'], $keys);
$storage = $this->getStorage();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop this line, replace all usages of $storage with $this->storage

@matej21
Copy link
Contributor Author

matej21 commented Apr 29, 2016

updated - storages are optimized

$keys = array_combine(array_map(function ($key) {
return urlencode($this->prefix . $key);
}, $keys), $keys);
$metas = $this->memcached->getMulti(array_keys($keys));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with

$prefixedKeys = array_map(function ($key) { return urlencode($this->prefix . $key); });
$keys = array_combine($prefixedKeys, $keys); // TODO: can we remove this?
$metas = $this->memcached->getMulti($prefixedKeys);

@dg dg force-pushed the master branch 3 times, most recently from 0aed862 to a0c400e Compare May 2, 2016 20:25
@dg dg force-pushed the master branch 2 times, most recently from 54c618b to 62a27d9 Compare May 19, 2016 00:29
@dg dg closed this in aa11160 Jun 12, 2016
dg pushed a commit that referenced this pull request Jun 12, 2016
dg pushed a commit that referenced this pull request Jun 12, 2016
dg pushed a commit that referenced this pull request Jun 14, 2016
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

Successfully merging this pull request may close these issues.

5 participants