| 3280 | } |
| 3281 | |
| 3282 | void redisDbPersistentData::prefetchKeysAsync(client *c, parsed_command &command) |
| 3283 | { |
| 3284 | if (m_spstorage == nullptr) { |
| 3285 | #if defined(__x86_64__) || defined(__i386__) |
| 3286 | // We do a quick 'n dirty check for set & get. Anything else is too slow. |
| 3287 | // Should the user do something weird like remap them then the worst that will |
| 3288 | // happen is we don't prefetch or we prefetch wrong data. A mild perf hit, but |
| 3289 | // not dangerous |
| 3290 | if (command.argc >= 2) { |
| 3291 | const char *cmd = szFromObj(command.argv[0]); |
| 3292 | if (!strcasecmp(cmd, "set") || !strcasecmp(cmd, "get")) { |
| 3293 | if (c->db->m_spdbSnapshotHOLDER != nullptr) |
| 3294 | return; // this is dangerous enough without a snapshot around |
| 3295 | auto h = dictSdsHash(szFromObj(command.argv[1])); |
| 3296 | for (int iht = 0; iht < 2; ++iht) { |
| 3297 | auto hT = h & c->db->m_pdict->ht[iht].sizemask; |
| 3298 | dictEntry **table; |
| 3299 | __atomic_load(&c->db->m_pdict->ht[iht].table, &table, __ATOMIC_RELAXED); |
| 3300 | if (table != nullptr) { |
| 3301 | dictEntry *de; |
| 3302 | __atomic_load(&table[hT], &de, __ATOMIC_ACQUIRE); |
| 3303 | while (de != nullptr) { |
| 3304 | _mm_prefetch(dictGetKey(de), _MM_HINT_T2); |
| 3305 | __atomic_load(&de->next, &de, __ATOMIC_ACQUIRE); |
| 3306 | } |
| 3307 | } |
| 3308 | if (!dictIsRehashing(c->db->m_pdict)) |
| 3309 | break; |
| 3310 | } |
| 3311 | } |
| 3312 | } |
| 3313 | #endif |
| 3314 | return; |
| 3315 | } |
| 3316 | |
| 3317 | AeLocker lock; |
| 3318 | |
| 3319 | std::vector<robj*> veckeys; |
| 3320 | lock.arm(c); |
| 3321 | getKeysResult result = GETKEYS_RESULT_INIT; |
| 3322 | auto cmd = lookupCommand(szFromObj(command.argv[0])); |
| 3323 | if (cmd == nullptr) |
| 3324 | return; // Bad command? It's not for us to judge, just bail |
| 3325 | |
| 3326 | if (command.argc < std::abs(cmd->arity)) |
| 3327 | return; // Invalid number of args |
| 3328 | |
| 3329 | int numkeys = getKeysFromCommand(cmd, command.argv, command.argc, &result); |
| 3330 | for (int ikey = 0; ikey < numkeys; ++ikey) |
| 3331 | { |
| 3332 | robj *objKey = command.argv[result.keys[ikey]]; |
| 3333 | if (this->find_cached_threadsafe(szFromObj(objKey)) == nullptr) |
| 3334 | veckeys.push_back(objKey); |
| 3335 | } |
| 3336 | lock.disarm(); |
| 3337 | |
| 3338 | getKeysFreeResult(&result); |
| 3339 |
no test coverage detected