}
}
+void EngineHyperscan::streamCompressExpand(EngineStream &stream,
+ vector<char> &temp) const {
+ size_t used = 0;
+ hs_error_t err = hs_compress_stream(stream.id, temp.data(), temp.size(),
+ &used);
+ if (err == HS_INSUFFICIENT_SPACE) {
+ temp.resize(used);
+ err = hs_compress_stream(stream.id, temp.data(), temp.size(), &used);
+ }
+
+ if (err != HS_SUCCESS) {
+ printf("Fatal error: hs_compress_stream returned error %d\n", err);
+ abort();
+ }
+
+ if (printCompressSize) {
+ printf("stream %u: compressed to %zu\n", stream.sn, used);
+ }
+
+ err = hs_reset_and_expand_stream(stream.id, temp.data(), temp.size(),
+ nullptr, nullptr, nullptr);
+
+ if (err != HS_SUCCESS) {
+ printf("Fatal error: hs_reset_and expand_stream returned error %d\n",
+ err);
+ abort();
+ }
+}
+
static
unsigned makeModeFlags(ScanMode scan_mode) {
switch (scan_mode) {
/*
- * Copyright (c) 2016, Intel Corporation
+ * Copyright (c) 2016-2017, Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
#include "hs_runtime.h"
#include <memory>
+#include <vector>
/** Structure for the result of a single complete scan. */
struct ResultEntry {
void streamClose(std::unique_ptr<EngineStream> stream,
ResultEntry &result) const;
+ void streamCompressExpand(EngineStream &stream,
+ std::vector<char> &temp) const;
+
void streamScan(EngineStream &stream, const char *data, unsigned int len,
unsigned int id, ResultEntry &result) const;
unsigned int somPrecisionMode = HS_MODE_SOM_HORIZON_LARGE;
bool forceEditDistance = false;
unsigned editDistance = 0;
+bool printCompressSize = false;
+
+// Globals local to this file.
+static bool compressStream = false;
namespace /* anonymous */ {
-// Globals local to this file.
bool display_per_scan = false;
ScanMode scan_mode = ScanMode::STREAMING;
unsigned repeats = 20;
int in_sigfile = 0;
int do_per_scan = 0;
int do_echo_matches = 0;
+ int do_compress = 0;
+ int do_compress_size = 0;
vector<string> sigFiles;
static struct option longopts[] = {
{"per-scan", 0, &do_per_scan, 1},
{"echo-matches", 0, &do_echo_matches, 1},
+ {"compress-stream", 0, &do_compress, 1},
+ {"print-compress-size", 0, &do_compress_size, 1},
{nullptr, 0, nullptr, 0}
};
if (do_per_scan) {
display_per_scan = true;
}
+ if (do_compress) {
+ compressStream = true;
+ }
+ if (do_compress_size) {
+ printCompressSize = true;
+ }
if (exprPath.empty() && !sigFiles.empty()) {
/* attempt to infer an expression directory */
}
static
-void benchStreamingInternal(ThreadContext *ctx, vector<StreamInfo> &streams) {
+void benchStreamingInternal(ThreadContext *ctx, vector<StreamInfo> &streams,
+ bool do_compress) {
assert(ctx);
const EngineHyperscan &e = ctx->engine;
const vector<DataBlock> &blocks = ctx->corpus_data;
+ vector<char> compress_buf(do_compress ? 1000 : 0);
for (ResultEntry &r : ctx->results) {
ctx->timer.start();
printf("Fatal error: stream open failed!\n");
exit(1);
}
+ } else if (do_compress) {
+ e.streamCompressExpand(*stream.eng_handle, compress_buf);
}
assert(stream.eng_handle);
startTotalTimer(ctx);
- benchStreamingInternal(ctx, streams);
+ benchStreamingInternal(ctx, streams, false);
// Synchronization point
ctx->barrier();
stopTotalTimer(ctx);
}
+static
+void benchStreamingCompress(void *context) {
+ ThreadContext *ctx = (ThreadContext *)context;
+ vector<StreamInfo> streams = prepStreamingData(ctx);
+
+ // Synchronization point
+ ctx->barrier();
+
+ startTotalTimer(ctx);
+
+ benchStreamingInternal(ctx, streams, true);
+
+ // Synchronization point
+ ctx->barrier();
+
+ // Now that all threads are finished, we can stop the clock.
+ stopTotalTimer(ctx);
+}
+
+
/** In-memory structure for a data block to be scanned in vectored mode. */
struct VectoredInfo {
vector<const char *> data;
thread_func_t fn = nullptr;
switch (scan_mode) {
case ScanMode::STREAMING:
- fn = benchStreaming;
+ if (compressStream) {
+ fn = benchStreamingCompress;
+ } else {
+ fn = benchStreaming;
+ }
break;
case ScanMode::VECTORED:
fn = benchVectored;