]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
roseCheckNfaEod: use sparse iterator for EOD
authorJustin Viiret <justin.viiret@intel.com>
Wed, 23 Dec 2015 04:12:28 +0000 (15:12 +1100)
committerMatthew Barr <matthew.barr@intel.com>
Tue, 1 Mar 2016 00:20:26 +0000 (11:20 +1100)
Rather than checking all active outfix/suffix engines, use a sparse
iterator to check only those engines that accept at EOD.

src/rose/eod.c
src/rose/rose_build_bytecode.cpp
src/rose/rose_dump.cpp
src/rose/rose_internal.h

index 014b51ca969772179fc371bd7f458258ab61dff3..a6524f9617ebc3b135ce38ba2ceef29c8dd10ed6 100644 (file)
@@ -125,33 +125,44 @@ int roseEodRunIterator(const struct RoseEngine *t, u64a offset,
     return MO_CONTINUE_MATCHING;
 }
 
+/**
+ * \brief Check for (and deliver) reports from active output-exposed (suffix
+ * or outfix) NFAs.
+ */
 static rose_inline
 void roseCheckNfaEod(const struct RoseEngine *t, u8 *state,
                      struct hs_scratch *scratch, u64a offset,
                      const char is_streaming) {
-    /* data, len is used for state decompress, should be full available data */
-    const u8 *aa = getActiveLeafArray(t, state);
-    const u32 aaCount = t->activeArrayCount;
+    if (!t->eodNfaIterOffset) {
+        DEBUG_PRINTF("no engines that report at EOD\n");
+        return;
+    }
 
+    /* data, len is used for state decompress, should be full available data */
     u8 key = 0;
-
     if (is_streaming) {
         const u8 *eod_data = scratch->core_info.hbuf;
         size_t eod_len = scratch->core_info.hlen;
         key = eod_len ? eod_data[eod_len - 1] : 0;
     }
 
-    for (u32 qi = mmbit_iterate(aa, aaCount, MMB_INVALID); qi != MMB_INVALID;
-         qi = mmbit_iterate(aa, aaCount, qi)) {
+    const u8 *aa = getActiveLeafArray(t, state);
+    const u32 aaCount = t->activeArrayCount;
+
+    const struct mmbit_sparse_iter *it = getByOffset(t, t->eodNfaIterOffset);
+    assert(ISALIGNED(it));
+
+    u32 idx = 0;
+    struct mmbit_sparse_state si_state[MAX_SPARSE_ITER_STATES];
+
+    for (u32 qi = mmbit_sparse_iter_begin(aa, aaCount, &idx, it, si_state);
+         qi != MMB_INVALID;
+         qi = mmbit_sparse_iter_next(aa, aaCount, qi, &idx, it, si_state)) {
         const struct NfaInfo *info = getNfaInfoByQueue(t, qi);
         const struct NFA *nfa = getNfaByInfo(t, info);
 
-        if (!nfaAcceptsEod(nfa)) {
-            DEBUG_PRINTF("nfa %u does not accept eod\n", qi);
-            continue;
-        }
-
         DEBUG_PRINTF("checking nfa %u\n", qi);
+        assert(nfaAcceptsEod(nfa));
 
         char *fstate = scratch->fullState + info->fullStateOffset;
         const char *sstate = (const char *)state + info->stateOffset;
index 9ba7fa35376367bd963c1066e12f2221c4fa0024..9c6a84b3d0101c37cca839b234ee1fbc2932b511 100644 (file)
@@ -2294,6 +2294,29 @@ void buildSuffixEkeyLists(const RoseBuildImpl &tbi, build_context &bc,
     }
 }
 
+/** Returns sparse iter offset in engine blob. */
+static
+u32 buildEodNfaIterator(build_context &bc, const u32 activeQueueCount) {
+    vector<u32> keys;
+    for (u32 qi = 0; qi < activeQueueCount; ++qi) {
+        const NFA *n = get_nfa_from_blob(bc, qi);
+        if (nfaAcceptsEod(n)) {
+            DEBUG_PRINTF("nfa qi=%u accepts eod\n", qi);
+            keys.push_back(qi);
+        }
+    }
+
+    if (keys.empty()) {
+        return 0;
+    }
+
+    DEBUG_PRINTF("building iter for %zu nfas\n", keys.size());
+
+    vector<mmbit_sparse_iter> iter;
+    mmbBuildSparseIterator(iter, keys, activeQueueCount);
+    return addIteratorToTable(bc, iter);
+}
+
 static
 bool hasMpvTrigger(const set<u32> &reports, const ReportManager &rm) {
     for (u32 r : reports) {
@@ -3802,6 +3825,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
                    &leftfixBeginQueue)) {
         return nullptr;
     }
+    u32 eodNfaIterOffset = buildEodNfaIterator(bc, leftfixBeginQueue);
     buildCountingMiracles(*this, bc);
 
     u32 queue_count = qif.allocated_count(); /* excludes anchored matcher q;
@@ -4054,6 +4078,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
     engine->eodProgramOffset = eodProgramOffset;
     engine->eodIterProgramOffset = eodIterProgramOffset;
     engine->eodIterOffset = eodIterOffset;
+    engine->eodNfaIterOffset = eodNfaIterOffset;
 
     engine->lastByteHistoryIterOffset = lastByteOffset;
 
index 3f355287c6fb41320753a5bfb4154694ed94c045..beadd23e246447068dd05f80e57d711a9bf7c45a 100644 (file)
@@ -861,6 +861,7 @@ void roseDumpStructRaw(const RoseEngine *t, FILE *f) {
     DUMP_U32(t, eodProgramOffset);
     DUMP_U32(t, eodIterProgramOffset);
     DUMP_U32(t, eodIterOffset);
+    DUMP_U32(t, eodNfaIterOffset);
     DUMP_U32(t, lastByteHistoryIterOffset);
     DUMP_U32(t, minWidth);
     DUMP_U32(t, minWidthExcludingBoundaries);
index 6234bb215e1bea14a31facfa4ca947bda545ac1a..1f927a2cb5a4b1c1936371456635f24c32960402 100644 (file)
@@ -428,6 +428,9 @@ struct RoseEngine {
     u32 eodIterProgramOffset; // or 0 if no eod iterator program
     u32 eodIterOffset; // offset to EOD sparse iter or 0 if none
 
+    /** \brief Offset to sparse iter over outfix/suffix NFAs that accept EOD. */
+    u32 eodNfaIterOffset;
+
     u32 lastByteHistoryIterOffset; // if non-zero
 
     /** \brief Minimum number of bytes required to match. */