Toshaan Bharvani
2 years ago
commit
ba5f9a941f
4 changed files with 1192 additions and 0 deletions
@ -0,0 +1,907 @@
@@ -0,0 +1,907 @@
|
||||
From 943a7f434b10c19f8e8e865c3cc40685b9903822 Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Thu, 24 Mar 2022 17:32:43 -0300 |
||||
Subject: [PATCH 1/6] Provide a maximum job length depending on the |
||||
virtualization |
||||
|
||||
Identify if a system is running on baremetal or PowerVM and provide |
||||
a maximum job length adapted to each case. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_inflate.c | 5 +++-- |
||||
lib/nx_zlib.c | 25 +++++++++++++++++++++++-- |
||||
lib/nx_zlib.h | 4 ++++ |
||||
3 files changed, 30 insertions(+), 4 deletions(-) |
||||
|
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index ec32b4c..77ad33c 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -945,8 +945,9 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
uint32_t write_sz, source_sz, target_sz; |
||||
long loop_cnt = 0, loop_max = 0xffff; |
||||
|
||||
- /* inflate benefits from large jobs; memcopies must be amortized */ |
||||
- uint32_t inflate_per_job_len = 64 * nx_config.per_job_len; |
||||
+ /** \brief inflate benefits from large jobs; memcopies must be |
||||
+ * amortized. */ |
||||
+ const uint32_t inflate_per_job_len = nx_config.per_job_len; |
||||
|
||||
/* nx hardware */ |
||||
uint32_t sfbt = 0, subc = 0, spbc, tpbc, nx_ce, fc; |
||||
diff --git a/lib/nx_zlib.c b/lib/nx_zlib.c |
||||
index 28ea482..a50d6f7 100644 |
||||
--- a/lib/nx_zlib.c |
||||
+++ b/lib/nx_zlib.c |
||||
@@ -64,6 +64,18 @@ |
||||
#include "nx_utils.h" |
||||
#include "nx_zlib.h" |
||||
|
||||
+/* Use the following values as maximum length of NX jobs when the OS doesn't |
||||
+ provide the value itself, which is the default behavior until Linux 5.17 */ |
||||
+ |
||||
+/** \brief Maximum job length on baremetal |
||||
+ * |
||||
+ * While the system does allow up-to 2 GiB as the maximum job length, restrict |
||||
+ * it to 64 MiB. |
||||
+ */ |
||||
+#define DEFAULT_MAX_JOB_BAREMETAL 64 * 1024 * 1024 |
||||
+/** \brief Maximum job length on PowerVM */ |
||||
+#define DEFAULT_MAX_JOB_POWERVM 1024 * 1024 |
||||
+ |
||||
struct nx_config_t nx_config; |
||||
static struct nx_dev_t nx_devices[NX_DEVICES_MAX]; |
||||
static int nx_dev_count = 0; |
||||
@@ -639,8 +651,13 @@ static int nx_query_job_limits() |
||||
} |
||||
} |
||||
|
||||
- /* On error return default value of 1 MB */ |
||||
- return (1024 * 1024); |
||||
+ /* On error return default value. */ |
||||
+ switch (nx_config.virtualization) { |
||||
+ case BAREMETAL: |
||||
+ return DEFAULT_MAX_JOB_BAREMETAL; |
||||
+ default: |
||||
+ return DEFAULT_MAX_JOB_POWERVM; |
||||
+ } |
||||
} |
||||
|
||||
/* |
||||
@@ -659,6 +676,9 @@ static int nx_enumerate_engines() |
||||
int count = 0; |
||||
size_t n; |
||||
|
||||
+ /* Assume baremetal by default. */ |
||||
+ nx_config.virtualization = BAREMETAL; |
||||
+ |
||||
d = opendir(DEVICE_TREE); |
||||
if (d == NULL){ |
||||
prt_err("open device tree dir failed.\n"); |
||||
@@ -712,6 +732,7 @@ static int nx_enumerate_engines() |
||||
} |
||||
/* On PowerVM, there is no concept of multiple NX engines. */ |
||||
if (strncmp(de->d_name, "ibm,powervm", 11) == 0){ |
||||
+ nx_config.virtualization = POWERVM; |
||||
closedir(d); |
||||
return 1; |
||||
} |
||||
diff --git a/lib/nx_zlib.h b/lib/nx_zlib.h |
||||
index e84bd7e..fa73b01 100644 |
||||
--- a/lib/nx_zlib.h |
||||
+++ b/lib/nx_zlib.h |
||||
@@ -129,6 +129,8 @@ void nx_print_dde(nx_dde_t *ddep, const char *msg); |
||||
#define zlib_version zlibVersion() |
||||
extern const char *zlibVersion OF((void)); |
||||
|
||||
+enum virtualization {BAREMETAL=0, POWERVM=1}; |
||||
+ |
||||
/* common config variables for all streams */ |
||||
struct nx_config_t { |
||||
long page_sz; |
||||
@@ -158,6 +160,8 @@ struct nx_config_t { |
||||
* dynamic huffman */ |
||||
struct selector mode; /** mode selector: selects between software |
||||
* and hardware compression. */ |
||||
+ uint8_t virtualization; /** Indicate the virtualization type being |
||||
+ * used. */ |
||||
}; |
||||
typedef struct nx_config_t *nx_configp_t; |
||||
extern struct nx_config_t nx_config; |
||||
|
||||
From b22eb7bffe61e36f70661921a689e44370d3c7e5 Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Thu, 24 Mar 2022 18:03:28 -0300 |
||||
Subject: [PATCH 2/6] inflate: Move code that initializes the DDE to their own |
||||
functions |
||||
|
||||
Create functions nx_reset_dde() and nx_init_dde() based on previous code |
||||
helping to reduce the size of nx_inflate_() and making it easier to |
||||
understand the code. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_inflate.c | 197 ++++++++++++++++++++++++++++------------------- |
||||
1 file changed, 116 insertions(+), 81 deletions(-) |
||||
|
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index 77ad33c..f1d9adb 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -934,6 +934,120 @@ static int copy_data_to_fifo_in(nx_streamp s) { |
||||
return Z_OK; |
||||
} |
||||
|
||||
+/** \brief Reset DDE to initial values. |
||||
+ * |
||||
+ * @param s nx_streamp to be processed. |
||||
+ * @return Function code as passed to CRB. The function will set the CRB and |
||||
+ * return the value here. |
||||
+ */ |
||||
+static int nx_reset_dde(nx_streamp s) { |
||||
+ nx_gzip_crb_cpb_t *cmdp = s->nxcmdp; |
||||
+ uint32_t fc; |
||||
+ |
||||
+ /* address/len lists */ |
||||
+ clearp_dde(s->ddl_in); |
||||
+ clearp_dde(s->ddl_out); |
||||
+ |
||||
+ /* FC, CRC, HistLen, Table 6-6 */ |
||||
+ if (s->resuming || (s->dict_len > 0)) { |
||||
+ /* Resuming a partially decompressed input. */ |
||||
+ fc = GZIP_FC_DECOMPRESS_RESUME; |
||||
+ } else { |
||||
+ /* First decompress job */ |
||||
+ fc = GZIP_FC_DECOMPRESS; |
||||
+ |
||||
+ /* We use the most recently measured compression ratio |
||||
+ as a heuristic to estimate the input and output |
||||
+ sizes. If we give too much input, the target buffer |
||||
+ overflows and NX cycles are wasted, and then we |
||||
+ must retry with smaller input size. 1000 is 100% */ |
||||
+ s->last_comp_ratio = 1000UL; |
||||
+ } |
||||
+ |
||||
+ /* clear then copy fc to the crb */ |
||||
+ cmdp->crb.gzip_fc = 0; |
||||
+ putnn(cmdp->crb, gzip_fc, fc); |
||||
+ |
||||
+ return fc; |
||||
+} |
||||
+ |
||||
+/** \brief Initialize DDE, appending a dictionary, if necessary. |
||||
+ * |
||||
+ * @param s nx_streamp to be processed. |
||||
+ * @return The history length |
||||
+ */ |
||||
+static int nx_init_dde(nx_streamp s) { |
||||
+ nx_gzip_crb_cpb_t *cmdp = s->nxcmdp; |
||||
+ int nx_history_len = s->history_len; |
||||
+ |
||||
+ /* FC, CRC, HistLen, Table 6-6 */ |
||||
+ if (s->resuming || (s->dict_len > 0)) { |
||||
+ /* Resuming a partially decompressed input. The key |
||||
+ to resume is supplying the max 32KB dictionary |
||||
+ (history) to NX, which is basically the last 32KB |
||||
+ or less of the output earlier produced. And also |
||||
+ make sure partial checksums are carried forward |
||||
+ */ |
||||
+ |
||||
+ /* Crc of prev job passed to the job to be resumed */ |
||||
+ put32(cmdp->cpb, in_crc, s->crc32); |
||||
+ put32(cmdp->cpb, in_adler, s->adler32); |
||||
+ |
||||
+ /* Round up the sizes to quadword. Section 2.10 |
||||
+ Rounding up will not segfault because |
||||
+ nx_alloc_buffer has padding at the beginning */ |
||||
+ |
||||
+ if (s->dict_len > 0) { |
||||
+ /* lays dict on top of hist */ |
||||
+ nx_history_len = nx_amend_history_with_dict(s); |
||||
+ |
||||
+ if (s->wrap == HEADER_ZLIB) { |
||||
+ /* in the raw mode pass crc as is; in the zlib |
||||
+ mode initialize them */ |
||||
+ put32(cmdp->cpb, in_crc, INIT_CRC ); |
||||
+ put32(cmdp->cpb, in_adler, INIT_ADLER); |
||||
+ put32(cmdp->cpb, out_crc, INIT_CRC ); |
||||
+ put32(cmdp->cpb, out_adler, INIT_ADLER); |
||||
+ } |
||||
+ print_dbg_info(s, __LINE__); |
||||
+ } else { |
||||
+ /* no dictionary here */ |
||||
+ ASSERT( s->dict_len == 0 ); |
||||
+ nx_history_len = (nx_history_len + NXQWSZ - 1) / NXQWSZ; |
||||
+ putnn(cmdp->cpb, in_histlen, nx_history_len); |
||||
+ /* convert to bytes */ |
||||
+ nx_history_len = nx_history_len * NXQWSZ; |
||||
+ |
||||
+ if (nx_history_len > 0) { |
||||
+ /* deflate history goes in first */ |
||||
+ ASSERT(s->cur_out >= nx_history_len); |
||||
+ nx_append_dde(s->ddl_in, |
||||
+ s->fifo_out + (s->cur_out |
||||
+ - nx_history_len), |
||||
+ nx_history_len); |
||||
+ } |
||||
+ print_dbg_info(s, __LINE__); |
||||
+ } |
||||
+ } else { |
||||
+ nx_history_len = s->history_len = 0; |
||||
+ /* writing a 0 clears out subc as well */ |
||||
+ cmdp->cpb.in_histlen = 0; |
||||
+ |
||||
+ /* initialize the crc values */ |
||||
+ put32(cmdp->cpb, in_crc, INIT_CRC ); |
||||
+ put32(cmdp->cpb, in_adler, INIT_ADLER); |
||||
+ put32(cmdp->cpb, out_crc, INIT_CRC ); |
||||
+ put32(cmdp->cpb, out_adler, INIT_ADLER); |
||||
+ } |
||||
+ |
||||
+ /* We use the most recently measured compression ratio as a heuristic |
||||
+ to estimate the input and output sizes. If we give too much input, |
||||
+ the target buffer overflows and NX cycles are wasted, and then we |
||||
+ must retry with smaller input size. 1000 is 100% */ |
||||
+ s->last_comp_ratio = NX_MAX(NX_MIN(1000UL, s->last_comp_ratio), 100L); |
||||
+ return nx_history_len; |
||||
+} |
||||
+ |
||||
/** \brief Internal implementation of inflate. |
||||
* |
||||
* @param s nx_streamp to be processed. |
||||
@@ -1075,87 +1189,8 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
|
||||
/* NX decompresses input data */ |
||||
|
||||
- /* address/len lists */ |
||||
- clearp_dde(ddl_in); |
||||
- clearp_dde(ddl_out); |
||||
- |
||||
- nx_history_len = s->history_len; |
||||
- |
||||
- /* FC, CRC, HistLen, Table 6-6 */ |
||||
- if (s->resuming || (s->dict_len > 0)) { |
||||
- /* Resuming a partially decompressed input. The key |
||||
- to resume is supplying the max 32KB dictionary |
||||
- (history) to NX, which is basically the last 32KB |
||||
- or less of the output earlier produced. And also |
||||
- make sure partial checksums are carried forward |
||||
- */ |
||||
- fc = GZIP_FC_DECOMPRESS_RESUME; |
||||
- |
||||
- /* Crc of prev job passed to the job to be resumed */ |
||||
- put32(cmdp->cpb, in_crc, s->crc32); |
||||
- put32(cmdp->cpb, in_adler, s->adler32); |
||||
- |
||||
- /* Round up the sizes to quadword. Section 2.10 |
||||
- Rounding up will not segfault because |
||||
- nx_alloc_buffer has padding at the beginning */ |
||||
- |
||||
- if (s->dict_len > 0) { |
||||
- /* lays dict on top of hist */ |
||||
- nx_history_len = nx_amend_history_with_dict(s); |
||||
- |
||||
- if (s->wrap == HEADER_ZLIB) { |
||||
- /* in the raw mode pass crc as is; in the zlib mode |
||||
- initialize them */ |
||||
- put32(cmdp->cpb, in_crc, INIT_CRC ); |
||||
- put32(cmdp->cpb, in_adler, INIT_ADLER); |
||||
- put32(cmdp->cpb, out_crc, INIT_CRC ); |
||||
- put32(cmdp->cpb, out_adler, INIT_ADLER); |
||||
- } |
||||
- |
||||
- s->last_comp_ratio = NX_MAX( NX_MIN(1000UL, s->last_comp_ratio), 100L ); |
||||
- |
||||
- print_dbg_info(s, __LINE__); |
||||
- } |
||||
- else { |
||||
- /* no dictionary here */ |
||||
- ASSERT( s->dict_len == 0 ); |
||||
- nx_history_len = (nx_history_len + NXQWSZ - 1) / NXQWSZ; |
||||
- putnn(cmdp->cpb, in_histlen, nx_history_len); |
||||
- nx_history_len = nx_history_len * NXQWSZ; /* convert to bytes */ |
||||
- |
||||
- if (nx_history_len > 0) { |
||||
- /* deflate history goes in first */ |
||||
- ASSERT(s->cur_out >= nx_history_len); |
||||
- nx_append_dde(ddl_in, s->fifo_out + (s->cur_out - nx_history_len), nx_history_len); |
||||
- } |
||||
- print_dbg_info(s, __LINE__); |
||||
- } |
||||
- } |
||||
- else { |
||||
- /* First decompress job */ |
||||
- fc = GZIP_FC_DECOMPRESS; |
||||
- |
||||
- nx_history_len = s->history_len = 0; |
||||
- /* writing a 0 clears out subc as well */ |
||||
- cmdp->cpb.in_histlen = 0; |
||||
- |
||||
- /* initialize the crc values */ |
||||
- put32(cmdp->cpb, in_crc, INIT_CRC ); |
||||
- put32(cmdp->cpb, in_adler, INIT_ADLER); |
||||
- put32(cmdp->cpb, out_crc, INIT_CRC ); |
||||
- put32(cmdp->cpb, out_adler, INIT_ADLER); |
||||
- |
||||
- /* We use the most recently measured compression ratio |
||||
- as a heuristic to estimate the input and output |
||||
- sizes. If we give too much input, the target buffer |
||||
- overflows and NX cycles are wasted, and then we |
||||
- must retry with smaller input size. 1000 is 100% */ |
||||
- s->last_comp_ratio = 1000UL; |
||||
- } |
||||
- |
||||
- /* clear then copy fc to the crb */ |
||||
- cmdp->crb.gzip_fc = 0; |
||||
- putnn(cmdp->crb, gzip_fc, fc); |
||||
+ fc = nx_reset_dde(s); |
||||
+ nx_history_len = nx_init_dde(s); |
||||
|
||||
/* |
||||
* NX source buffers |
||||
|
||||
From e376d92fa704108f1258e3a41fc1ffcf551d1c5b Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Fri, 25 Mar 2022 09:57:32 -0300 |
||||
Subject: [PATCH 3/6] Fix the total amount of pages being touched |
||||
|
||||
Fix and error in nx_touch_pages_dde() that was causing the function to |
||||
touch a different number of pages than requested. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_zlib.c | 2 +- |
||||
1 file changed, 1 insertion(+), 1 deletion(-) |
||||
|
||||
diff --git a/lib/nx_zlib.c b/lib/nx_zlib.c |
||||
index a50d6f7..bf2a6fc 100644 |
||||
--- a/lib/nx_zlib.c |
||||
+++ b/lib/nx_zlib.c |
||||
@@ -398,7 +398,7 @@ int nx_touch_pages_dde(nx_dde_t *ddep, long buf_sz, long page_sz, int wr) |
||||
|
||||
/* touching fewer pages than encoded in the ddebc */ |
||||
if ( total > buf_sz) { |
||||
- buf_len = NX_MIN(buf_len, total - buf_sz); |
||||
+ buf_len = buf_sz - (total - buf_len); |
||||
nx_touch_pages((void *)buf_addr, buf_len, page_sz, wr); |
||||
prt_trace("touch loop break len 0x%x ddead %p\n", buf_len, (void *)buf_addr); |
||||
break; |
||||
|
||||
From 1f3dc128a476c9bbbb1b503d2fc8f54365101ebf Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Thu, 24 Mar 2022 18:18:34 -0300 |
||||
Subject: [PATCH 4/6] inflate: Move code that sets the DDE |
||||
|
||||
Create functions nx_set_dde_in() and nx_set_dde_out() based on old code. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_inflate.c | 64 +++++++++++++++++++++++++++++++++--------------- |
||||
1 file changed, 44 insertions(+), 20 deletions(-) |
||||
|
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index f1d9adb..a9671b2 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -1048,6 +1048,41 @@ static int nx_init_dde(nx_streamp s) { |
||||
return nx_history_len; |
||||
} |
||||
|
||||
+/** \brief Append input data to DDE |
||||
+ * |
||||
+ * @param s nx_streamp to be processed. |
||||
+ * |
||||
+ * @return The total amount of bytes appended to DDE |
||||
+ */ |
||||
+static uint32_t nx_set_dde_in(nx_streamp s) { |
||||
+ /* Buffered user input is next */ |
||||
+ if (s->fifo_in != NULL) |
||||
+ nx_append_dde(s->ddl_in, s->fifo_in + s->cur_in, s->used_in); |
||||
+ /* Then current user input. */ |
||||
+ nx_append_dde(s->ddl_in, s->next_in, s->avail_in); |
||||
+ /* Total bytes going in to engine. */ |
||||
+ return getp32(s->ddl_in, ddebc); |
||||
+} |
||||
+ |
||||
+/** \brief Append output data to DDE |
||||
+ * |
||||
+ * @param s nx_streamp to be processed. |
||||
+ * |
||||
+ * @return The total amount of bytes appended to DDE |
||||
+ */ |
||||
+static uint32_t nx_set_dde_out(nx_streamp s) { |
||||
+ /* Decompress to user buffer first. */ |
||||
+ nx_append_dde(s->ddl_out, s->next_out, s->avail_out); |
||||
+ |
||||
+ /* Overflow to fifo_out. |
||||
+ used_out == 0 required by definition. */ |
||||
+ ASSERT(s->used_out == 0); |
||||
+ nx_append_dde(s->ddl_out, s->fifo_out + s->cur_out, |
||||
+ s->len_out - s->cur_out); |
||||
+ |
||||
+ return s->avail_out + s->len_out - s->cur_out; |
||||
+} |
||||
+ |
||||
/** \brief Internal implementation of inflate. |
||||
* |
||||
* @param s nx_streamp to be processed. |
||||
@@ -1195,28 +1230,13 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
/* |
||||
* NX source buffers |
||||
*/ |
||||
- /* buffered user input is next */ |
||||
- if (s->fifo_in != NULL) |
||||
- nx_append_dde(ddl_in, s->fifo_in + s->cur_in, s->used_in); |
||||
- /* then current user input */ |
||||
- nx_append_dde(ddl_in, s->next_in, s->avail_in); |
||||
- source_sz = getp32(ddl_in, ddebc); /* total bytes going in to engine */ |
||||
- ASSERT( source_sz > nx_history_len ); |
||||
+ source_sz = nx_set_dde_in(s); |
||||
+ ASSERT(source_sz > nx_history_len); |
||||
|
||||
/* |
||||
* NX target buffers |
||||
*/ |
||||
- ASSERT(s->used_out == 0); |
||||
- |
||||
- uint32_t len_next_out = s->avail_out; |
||||
- nx_append_dde(ddl_out, s->next_out, len_next_out); /* decomp in to user buffer */ |
||||
- |
||||
- /* overflow, used_out == 0 required by definition, +used_out below is unnecessary */ |
||||
- nx_append_dde(ddl_out, s->fifo_out + s->cur_out + s->used_out, s->len_out - s->cur_out - s->used_out); |
||||
- target_sz = len_next_out + s->len_out - s->cur_out - s->used_out; |
||||
- |
||||
- prt_info("len_next_out %d len_out %d cur_out %d used_out %d source_sz %d history_len %d\n", |
||||
- len_next_out, s->len_out, s->cur_out, s->used_out, source_sz, nx_history_len); |
||||
+ target_sz = nx_set_dde_out(s); |
||||
|
||||
/* We want exactly the History size amount of 32KB to overflow |
||||
in to fifo_out. If overflow is less, the history spans |
||||
@@ -1228,6 +1248,7 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
these copies (memcpy) for performance. Therefore, the |
||||
heuristic here will estimate the source size for the |
||||
desired target size */ |
||||
+ uint32_t len_next_out = s->avail_out; |
||||
|
||||
/* avail_out plus 32 KB history plus a bit of overhead */ |
||||
uint32_t target_sz_expected = len_next_out + INF_HIS_LEN + (INF_HIS_LEN >> 2); |
||||
@@ -1240,11 +1261,14 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
|
||||
prt_info("target_sz_expected %d source_sz_expected %d source_sz %d last_comp_ratio %d nx_history_len %d\n", target_sz_expected, source_sz_expected, source_sz, s->last_comp_ratio, nx_history_len); |
||||
|
||||
+ prt_info("%s:%d len_next_out %d len_out %d cur_out %d" |
||||
+ " used_out %d source_sz %d history_len %d\n", |
||||
+ __FUNCTION__, __LINE__, len_next_out, s->len_out, s->cur_out, |
||||
+ s->used_out, source_sz, nx_history_len); |
||||
+ |
||||
/* do not include input side history in the estimation */ |
||||
source_sz = source_sz - nx_history_len; |
||||
- |
||||
ASSERT(source_sz > 0); |
||||
- |
||||
source_sz = NX_MIN(source_sz, source_sz_expected); |
||||
|
||||
/* add the history back */ |
||||
|
||||
From eb6cb7b01fe1fa337979353e905e3ad96514b233 Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Thu, 24 Mar 2022 18:37:27 -0300 |
||||
Subject: [PATCH 5/6] inflate: cosmetic improvements |
||||
|
||||
- Add source code comments. |
||||
- Improve indentation. |
||||
- Break long lines. |
||||
- Fix error and information messages. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_inflate.c | 51 ++++++++++++++++++++++++++++++++++++------------ |
||||
1 file changed, 38 insertions(+), 13 deletions(-) |
||||
|
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index a9671b2..a6070bd 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -1090,14 +1090,31 @@ static uint32_t nx_set_dde_out(nx_streamp s) { |
||||
*/ |
||||
static int nx_inflate_(nx_streamp s, int flush) |
||||
{ |
||||
- /* queuing, file ops, byte counting */ |
||||
- uint32_t write_sz, source_sz, target_sz; |
||||
+ /** \brief Sum of the bytes that may be used by NX as input |
||||
+ * |
||||
+ * Total amount of bytes sent to the NX to be used as input, |
||||
+ * i.e. sum of the bytes in next_in and fifo_in. */ |
||||
+ uint32_t source_sz; |
||||
+ |
||||
+ /** \brief Sum of the bytes that may be used by NX as output |
||||
+ * |
||||
+ * Maximum amount of bytes available by the NX to be used as output, |
||||
+ * i.e. sum of the bytes available in next_out and fifo_out. */ |
||||
+ uint32_t target_sz; |
||||
+ |
||||
+ uint32_t write_sz; |
||||
long loop_cnt = 0, loop_max = 0xffff; |
||||
|
||||
/** \brief inflate benefits from large jobs; memcopies must be |
||||
* amortized. */ |
||||
const uint32_t inflate_per_job_len = nx_config.per_job_len; |
||||
|
||||
+ /** \brief Estimated value for target_sz. Used to calculate |
||||
+ * source_sz_expected. */ |
||||
+ uint32_t target_sz_expected; |
||||
+ /** \brief Estimated value for source_sz. */ |
||||
+ uint32_t source_sz_expected; |
||||
+ |
||||
/* nx hardware */ |
||||
uint32_t sfbt = 0, subc = 0, spbc, tpbc, nx_ce, fc; |
||||
|
||||
@@ -1251,16 +1268,20 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
uint32_t len_next_out = s->avail_out; |
||||
|
||||
/* avail_out plus 32 KB history plus a bit of overhead */ |
||||
- uint32_t target_sz_expected = len_next_out + INF_HIS_LEN + (INF_HIS_LEN >> 2); |
||||
+ target_sz_expected = len_next_out + INF_HIS_LEN + (INF_HIS_LEN >> 2); |
||||
|
||||
target_sz_expected = NX_MIN(target_sz_expected, inflate_per_job_len); |
||||
|
||||
/* e.g. if we want 100KB at the output and if the compression |
||||
ratio is 10% we want 10KB if input */ |
||||
- uint32_t source_sz_expected = (uint32_t)(((uint64_t)target_sz_expected * s->last_comp_ratio + 1000L)/1000UL); |
||||
+ source_sz_expected = (uint32_t) (((uint64_t) target_sz_expected |
||||
+ * s->last_comp_ratio + 1000L)/1000UL); |
||||
|
||||
- prt_info("target_sz_expected %d source_sz_expected %d source_sz %d last_comp_ratio %d nx_history_len %d\n", target_sz_expected, source_sz_expected, source_sz, s->last_comp_ratio, nx_history_len); |
||||
|
||||
+ prt_info("%s:%d target_sz_expected %d source_sz_expected %d" |
||||
+ " source_sz %d last_comp_ratio %d nx_history_len %d\n", |
||||
+ __FUNCTION__, __LINE__, target_sz_expected, source_sz_expected, |
||||
+ source_sz, s->last_comp_ratio, nx_history_len); |
||||
prt_info("%s:%d len_next_out %d len_out %d cur_out %d" |
||||
" used_out %d source_sz %d history_len %d\n", |
||||
__FUNCTION__, __LINE__, len_next_out, s->len_out, s->cur_out, |
||||
@@ -1280,8 +1301,11 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
|
||||
/* fault in pages */ |
||||
nx_touch_pages_dde(ddl_in, source_sz, nx_config.page_sz, 0); |
||||
- nx_touch_pages_dde(ddl_out, target_sz, nx_config.page_sz, 1); |
||||
- nx_touch_pages( (void *)cmdp, sizeof(nx_gzip_crb_cpb_t), nx_config.page_sz, 0); |
||||
+ nx_touch_pages_dde(ddl_out, |
||||
+ target_sz, |
||||
+ nx_config.page_sz, 1); |
||||
+ nx_touch_pages((void *) cmdp, sizeof(nx_gzip_crb_cpb_t), |
||||
+ nx_config.page_sz, 0); |
||||
|
||||
/* |
||||
* send job to NX |
||||
@@ -1298,9 +1322,9 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
faulting address to fsaddr */ |
||||
print_dbg_info(s, __LINE__); |
||||
|
||||
- prt_warn("ERR_NX_AT_FAULT: crb.csb.fsaddr %p source_sz %d ", |
||||
- (void *)cmdp->crb.csb.fsaddr, source_sz); |
||||
- prt_warn("target_sz %d\n", target_sz); |
||||
+ prt_warn("ERR_NX_AT_FAULT: crb.csb.fsaddr %p source_sz %d " |
||||
+ "target_sz %d\n", (void *)cmdp->crb.csb.fsaddr, |
||||
+ source_sz, target_sz); |
||||
#ifdef NX_LOG_SOURCE_TARGET |
||||
nx_print_dde(ddl_in, "source"); |
||||
nx_print_dde(ddl_out, "target"); |
||||
@@ -1339,8 +1363,8 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
if (ticks_total > (timeout_pgfaults * nx_get_freq())) { |
||||
/* TODO what to do when page faults are too many? |
||||
* Kernel MM would have killed the process. */ |
||||
- prt_err("Cannot make progress; too many page"); |
||||
- prt_err(" faults cc= %d\n", cc); |
||||
+ prt_err("Cannot make progress; too many page" |
||||
+ " faults cc= %d\n", cc); |
||||
} |
||||
else { |
||||
prt_warn("ERR_NX_AT_FAULT: more retry\n"); |
||||
@@ -1397,7 +1421,8 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
cover the max expansion of INF_MIN_INPUT_LEN |
||||
bytes */ |
||||
|
||||
- prt_info("ERR_NX_TARGET_SPACE; retry with smaller input data src %d hist %d\n", source_sz, nx_history_len); |
||||
+ prt_info("ERR_NX_TARGET_SPACE; retry with smaller input data" |
||||
+ " src %d hist %d\n", source_sz, nx_history_len); |
||||
goto restart_nx; |
||||
|
||||
case ERR_NX_OK: |
||||
|
||||
From 806bf8e3ed1d0ae8a21bc6b2035df390f1062c26 Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Mon, 28 Mar 2022 18:15:37 -0300 |
||||
Subject: [PATCH 6/6] inflate: Limit the amount of data added to the DDE |
||||
|
||||
Stop adding all input and output data to the DDE and limit based on the |
||||
calculated value for source_sz_expected and target_sz_expected. |
||||
By limiting these values, we end up better estimating the amount of |
||||
pages that need to be touched, reducing the amount of time spent |
||||
touching pages that might not be used. |
||||
|
||||
Reported-by: Puvichakravarthy Ramachandran <puvichakravarthy@in.ibm.com> |
||||
Reported-by: Poorna Chandra Vemula <Poorna.Chandra.Vemula@ibm.com> |
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_inflate.c | 180 +++++++++++++++++++++++++++++------------------ |
||||
1 file changed, 111 insertions(+), 69 deletions(-) |
||||
|
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index a6070bd..b30cdf6 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -955,13 +955,6 @@ static int nx_reset_dde(nx_streamp s) { |
||||
} else { |
||||
/* First decompress job */ |
||||
fc = GZIP_FC_DECOMPRESS; |
||||
- |
||||
- /* We use the most recently measured compression ratio |
||||
- as a heuristic to estimate the input and output |
||||
- sizes. If we give too much input, the target buffer |
||||
- overflows and NX cycles are wasted, and then we |
||||
- must retry with smaller input size. 1000 is 100% */ |
||||
- s->last_comp_ratio = 1000UL; |
||||
} |
||||
|
||||
/* clear then copy fc to the crb */ |
||||
@@ -1051,15 +1044,24 @@ static int nx_init_dde(nx_streamp s) { |
||||
/** \brief Append input data to DDE |
||||
* |
||||
* @param s nx_streamp to be processed. |
||||
+ * @param source_sz_expected The total amount of bytes expected as input. It |
||||
+ * does not include dictionary or history. |
||||
* |
||||
* @return The total amount of bytes appended to DDE |
||||
*/ |
||||
-static uint32_t nx_set_dde_in(nx_streamp s) { |
||||
+static uint32_t nx_set_dde_in(nx_streamp s, uint32_t source_sz_expected) { |
||||
+ uint32_t tmp = 0; |
||||
+ |
||||
/* Buffered user input is next */ |
||||
- if (s->fifo_in != NULL) |
||||
- nx_append_dde(s->ddl_in, s->fifo_in + s->cur_in, s->used_in); |
||||
- /* Then current user input. */ |
||||
- nx_append_dde(s->ddl_in, s->next_in, s->avail_in); |
||||
+ if (s->fifo_in != NULL) { |
||||
+ tmp = NX_MIN(s->used_in, source_sz_expected); |
||||
+ nx_append_dde(s->ddl_in, s->fifo_in + s->cur_in, tmp); |
||||
+ } |
||||
+ if (tmp < source_sz_expected) { |
||||
+ tmp = NX_MIN(s->avail_in, source_sz_expected - tmp); |
||||
+ /* Then current user input. */ |
||||
+ nx_append_dde(s->ddl_in, s->next_in, tmp); |
||||
+ } |
||||
/* Total bytes going in to engine. */ |
||||
return getp32(s->ddl_in, ddebc); |
||||
} |
||||
@@ -1067,20 +1069,32 @@ static uint32_t nx_set_dde_in(nx_streamp s) { |
||||
/** \brief Append output data to DDE |
||||
* |
||||
* @param s nx_streamp to be processed. |
||||
+ * @param target_sz_expected The total amount of bytes expected as output. |
||||
* |
||||
* @return The total amount of bytes appended to DDE |
||||
*/ |
||||
-static uint32_t nx_set_dde_out(nx_streamp s) { |
||||
+static uint32_t nx_set_dde_out(nx_streamp s, uint32_t target_sz_expected) { |
||||
+ uint32_t tmp; |
||||
+ uint32_t ret; |
||||
+ |
||||
+ ret = NX_MIN(s->avail_out, target_sz_expected); |
||||
+ |
||||
/* Decompress to user buffer first. */ |
||||
- nx_append_dde(s->ddl_out, s->next_out, s->avail_out); |
||||
+ nx_append_dde(s->ddl_out, s->next_out, ret); |
||||
+ |
||||
+ if (ret < target_sz_expected) { |
||||
+ tmp = NX_MIN(s->len_out - s->cur_out, |
||||
+ target_sz_expected - ret); |
||||
+ |
||||
+ /* Overflow to fifo_out. |
||||
+ used_out == 0 required by definition. */ |
||||
+ ASSERT(s->used_out == 0); |
||||
+ nx_append_dde(s->ddl_out, s->fifo_out + s->cur_out, tmp); |
||||
|
||||
- /* Overflow to fifo_out. |
||||
- used_out == 0 required by definition. */ |
||||
- ASSERT(s->used_out == 0); |
||||
- nx_append_dde(s->ddl_out, s->fifo_out + s->cur_out, |
||||
- s->len_out - s->cur_out); |
||||
+ ret += tmp; |
||||
+ } |
||||
|
||||
- return s->avail_out + s->len_out - s->cur_out; |
||||
+ return ret; |
||||
} |
||||
|
||||
/** \brief Internal implementation of inflate. |
||||
@@ -1094,7 +1108,7 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
* |
||||
* Total amount of bytes sent to the NX to be used as input, |
||||
* i.e. sum of the bytes in next_in and fifo_in. */ |
||||
- uint32_t source_sz; |
||||
+ uint32_t source_sz = 0; |
||||
|
||||
/** \brief Sum of the bytes that may be used by NX as output |
||||
* |
||||
@@ -1242,46 +1256,69 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
/* NX decompresses input data */ |
||||
|
||||
fc = nx_reset_dde(s); |
||||
- nx_history_len = nx_init_dde(s); |
||||
|
||||
- /* |
||||
- * NX source buffers |
||||
- */ |
||||
- source_sz = nx_set_dde_in(s); |
||||
- ASSERT(source_sz > nx_history_len); |
||||
+ /** Estimate the amount of data sent to the NX. Ideally, we want |
||||
+ * exactly the history size amount of 32 KiB to overflow in to fifo_out |
||||
+ * in order to minimize copies of memory. |
||||
+ * If overflow is less than 32 KiB, the history spans next_out and |
||||
+ * fifo_out and must be copied in to fifo_out to setup history for the |
||||
+ * next job. The fifo_out fraction is also copied back to user's |
||||
+ * next_out before the next job. |
||||
+ * If overflow is more, all the overflow must be copied back |
||||
+ * to user's next_out before the next job. |
||||
+ * If overflow is much more, we may get an ERR_NX_TARGET_SPACE, forcing |
||||
+ * us to reduce the source before trying again. A retry in this case |
||||
+ * will probably require NX to process much more than 32 KiB, which |
||||
+ * requires more time than copying 32 KiB of data. |
||||
+ * |
||||
+ * With that said, we want to minimize unecessary work (i.e. memcpy |
||||
+ * and retrying NX jobs) for performance. Therefore, the heuristic |
||||
+ * here will estimate the source size for the desired target size, but |
||||
+ * it prioritizes avoiding ERR_NX_TARGET_SPACE. */ |
||||
|
||||
- /* |
||||
- * NX target buffers |
||||
- */ |
||||
- target_sz = nx_set_dde_out(s); |
||||
- |
||||
- /* We want exactly the History size amount of 32KB to overflow |
||||
- in to fifo_out. If overflow is less, the history spans |
||||
- next_out and fifo_out and must be copied in to fifo_out to |
||||
- setup history for the next job, and the fifo_out fraction is |
||||
- also copied back to user's next_out before the next job. |
||||
- If overflow is more, all the overflow must be copied back |
||||
- to user's next_out before the next job. We want to minimize |
||||
- these copies (memcpy) for performance. Therefore, the |
||||
- heuristic here will estimate the source size for the |
||||
- desired target size */ |
||||
uint32_t len_next_out = s->avail_out; |
||||
+ s->last_comp_ratio = NX_MAX(NX_MIN(1000UL, s->last_comp_ratio), 100L); |
||||
|
||||
- /* avail_out plus 32 KB history plus a bit of overhead */ |
||||
+ /* avail_out plus 32 KiB history plus a bit of overhead */ |
||||
target_sz_expected = len_next_out + INF_HIS_LEN + (INF_HIS_LEN >> 2); |
||||
- |
||||
target_sz_expected = NX_MIN(target_sz_expected, inflate_per_job_len); |
||||
|
||||
- /* e.g. if we want 100KB at the output and if the compression |
||||
- ratio is 10% we want 10KB if input */ |
||||
+ /** Calculate source_sz_expected based on target_sz_expected and the |
||||
+ * last compression ratio, e.g. if we want 100KB at the output and if |
||||
+ * the compression ratio is 10% we want 10KB if input */ |
||||
source_sz_expected = (uint32_t) (((uint64_t) target_sz_expected |
||||
* s->last_comp_ratio + 1000L)/1000UL); |
||||
|
||||
+ /** After calculating source_sz_expected, try to provide extra |
||||
+ * target_sz_expected in order to avoid an ERR_NX_TARGET_SPACE. */ |
||||
+ target_sz_expected = NX_MIN(len_next_out + INF_HIS_LEN + (INF_HIS_LEN >> 2), |
||||
+ 4 * inflate_per_job_len); |
||||
+ prt_info("%s:%d target_sz_expected %d source_sz_expected %d" |
||||
+ " source_sz %d last_comp_ratio %d\n", |
||||
+ __FUNCTION__, __LINE__, target_sz_expected, source_sz_expected, |
||||
+ source_sz, s->last_comp_ratio); |
||||
+ |
||||
+ |
||||
+init_dde: |
||||
+ nx_history_len = nx_init_dde(s); |
||||
+ |
||||
+ /* |
||||
+ * NX source buffers |
||||
+ */ |
||||
+ source_sz = nx_set_dde_in(s, source_sz_expected); |
||||
+ ASSERT(source_sz > nx_history_len); |
||||
+ ASSERT(source_sz <= source_sz_expected + nx_history_len); |
||||
|
||||
prt_info("%s:%d target_sz_expected %d source_sz_expected %d" |
||||
" source_sz %d last_comp_ratio %d nx_history_len %d\n", |
||||
__FUNCTION__, __LINE__, target_sz_expected, source_sz_expected, |
||||
source_sz, s->last_comp_ratio, nx_history_len); |
||||
+ |
||||
+ /* |
||||
+ * NX target buffers |
||||
+ */ |
||||
+ target_sz = nx_set_dde_out(s, target_sz_expected); |
||||
+ |
||||
prt_info("%s:%d len_next_out %d len_out %d cur_out %d" |
||||
" used_out %d source_sz %d history_len %d\n", |
||||
__FUNCTION__, __LINE__, len_next_out, s->len_out, s->cur_out, |
||||
@@ -1345,19 +1382,22 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
that is about 2 pages minimum for source and |
||||
and 6 pages for target; if the system does not |
||||
have 8 free pages then the loop will last forever */ |
||||
- source_sz = source_sz - nx_history_len; |
||||
- if (source_sz > (2 * INF_MIN_INPUT_LEN)) |
||||
- source_sz = (source_sz + 1) / 2; |
||||
- else if (source_sz > INF_MIN_INPUT_LEN) |
||||
- source_sz = INF_MIN_INPUT_LEN; |
||||
- |
||||
- /* else if caller gave fewer source bytes, keep it as is */ |
||||
- source_sz = source_sz + nx_history_len; |
||||
- |
||||
- if (target_sz > (2 * INF_MAX_EXPANSION_BYTES)) |
||||
- target_sz = (target_sz + 1) / 2; |
||||
- else if (target_sz > INF_MAX_EXPANSION_BYTES) |
||||
- target_sz = INF_MAX_EXPANSION_BYTES; |
||||
+ source_sz_expected = source_sz - nx_history_len; |
||||
+ if (source_sz_expected > (2 * INF_MIN_INPUT_LEN)) |
||||
+ source_sz_expected |
||||
+ = (source_sz_expected + 1) / 2; |
||||
+ else if (source_sz_expected > INF_MIN_INPUT_LEN) |
||||
+ source_sz_expected = INF_MIN_INPUT_LEN; |
||||
+ |
||||
+ /* else if caller gave fewer source bytes, keep it as |
||||
+ is. */ |
||||
+ source_sz = source_sz_expected + nx_history_len; |
||||
+ |
||||
+ if (target_sz_expected > (2 * INF_MAX_EXPANSION_BYTES)) |
||||
+ target_sz_expected |
||||
+ = (target_sz_expected + 1) / 2; |
||||
+ else if (target_sz_expected > INF_MAX_EXPANSION_BYTES) |
||||
+ target_sz_expected = INF_MAX_EXPANSION_BYTES; |
||||
|
||||
ticks_total = nx_wait_ticks(500, ticks_total, 0); |
||||
if (ticks_total > (timeout_pgfaults * nx_get_freq())) { |
||||
@@ -1368,7 +1408,8 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
} |
||||
else { |
||||
prt_warn("ERR_NX_AT_FAULT: more retry\n"); |
||||
- goto restart_nx; |
||||
+ fc = nx_reset_dde(s); |
||||
+ goto init_dde; |
||||
} |
||||
} |
||||
|
||||
@@ -1403,18 +1444,17 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
/* Target buffer not large enough; retry smaller input |
||||
data; give at least 1 byte. SPBC/TPBC are not valid */ |
||||
ASSERT( source_sz > nx_history_len ); |
||||
- source_sz = ((source_sz - nx_history_len + 1) / 2) + nx_history_len; |
||||
+ source_sz_expected = (source_sz - nx_history_len + 1) / 2; |
||||
|
||||
- source_sz = source_sz - nx_history_len; |
||||
/* reduce large source down to minimum viable; if |
||||
source is already small don't change it */ |
||||
- if (source_sz > (2 * INF_MIN_INPUT_LEN)) |
||||
- source_sz = (source_sz + 1) / 2; |
||||
- else if (source_sz > INF_MIN_INPUT_LEN) |
||||
- source_sz = INF_MIN_INPUT_LEN; |
||||
+ if (source_sz_expected > (2 * INF_MIN_INPUT_LEN)) |
||||
+ source_sz_expected = (source_sz_expected + 1) / 2; |
||||
+ else if (source_sz_expected > INF_MIN_INPUT_LEN) |
||||
+ source_sz_expected = INF_MIN_INPUT_LEN; |
||||
|
||||
/* else if caller gave fewer source bytes, keep it as is */ |
||||
- source_sz = source_sz + nx_history_len; |
||||
+ source_sz = source_sz_expected + nx_history_len; |
||||
|
||||
/* do not change target size because we allocated a |
||||
minimum of INF_MAX_EXPANSION_BYTES which should |
||||
@@ -1422,8 +1462,10 @@ static int nx_inflate_(nx_streamp s, int flush) |
||||
bytes */ |
||||
|
||||
prt_info("ERR_NX_TARGET_SPACE; retry with smaller input data" |
||||
- " src %d hist %d\n", source_sz, nx_history_len); |
||||
- goto restart_nx; |
||||
+ " source_sz_expected %d nx_history_len %d\n", |
||||
+ source_sz_expected, nx_history_len); |
||||
+ fc = nx_reset_dde(s); |
||||
+ goto init_dde; |
||||
|
||||
case ERR_NX_OK: |
||||
|
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
From e639fe97eabe40445ad6c1308125ce8c2687ec6f Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Thu, 7 Apr 2022 16:40:37 -0300 |
||||
Subject: [PATCH] Increase the value for max_vas_reuse_count |
||||
|
||||
While running tests on PowerVM with 1MB files, it has been noticed a |
||||
huge delay when processing the 100th stream. |
||||
The penalty for reopening the VAS window is still too high for 100 |
||||
executions and is being increased to 10000 in order to keep its execution less |
||||
than 10% of the time spent executing those 10000 streams. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_zlib.c | 13 ++++++++++++- |
||||
test/nx-zlib.conf | 4 ++-- |
||||
2 files changed, 14 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/lib/nx_zlib.c b/lib/nx_zlib.c |
||||
index fa7000e..b3737a2 100644 |
||||
--- a/lib/nx_zlib.c |
||||
+++ b/lib/nx_zlib.c |
||||
@@ -982,7 +982,18 @@ void nx_hw_init(void) |
||||
nx_config.max_byte_count_current = (1UL<<30); |
||||
nx_config.max_source_dde_count = MAX_DDE_COUNT; |
||||
nx_config.max_target_dde_count = MAX_DDE_COUNT; |
||||
- nx_config.max_vas_reuse_count = 100; |
||||
+ /** On PowerVM, reopening a VAS window takes 300x the time used to |
||||
+ * process a single stream with the maximum per job length allowed, |
||||
+ * causing serious performance issues when max_vas_reuse_count is too |
||||
+ * low. In order to avoid these issues, it has been decided the |
||||
+ * average impact of reopening a VAS window should be less than 10% of |
||||
+ * of the time spent processing max_vas_reuse_count streams at |
||||
+ * maximum per job length. That means 3000, which we rounded up. |
||||
+ * Notice that setting this number too high may impact the performance |
||||
+ * of multithreaded processes with a massive amount of threads. For |
||||
+ * those cases, it's recommended to use a lower value in the config |
||||
+ * file. */ |
||||
+ nx_config.max_vas_reuse_count = 10000; |
||||
nx_config.per_job_len = nx_query_job_limits(); /* less than suspend limit */ |
||||
nx_config.strm_def_bufsz = (1024 * 1024); /* affect the deflate fifo_out */ |
||||
nx_config.soft_copy_threshold = 1024; /* choose memcpy or hwcopy */ |
||||
diff --git a/test/nx-zlib.conf b/test/nx-zlib.conf |
||||
index 444d966..cb30c36 100644 |
||||
--- a/test/nx-zlib.conf |
||||
+++ b/test/nx-zlib.conf |
||||
@@ -59,5 +59,5 @@ logfile = ./nx.log |
||||
#nx_ratio_s = 100 |
||||
|
||||
# Maximum number of times deflateInit/inflateInit can reuse an already-open VAS |
||||
-# window |
||||
-# max_vas_reuse_count = 100 |
||||
+# window. Default: 10000 |
||||
+# max_vas_reuse_count = 10000 |
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
From f8b15699d654c8ace6819287dcdd3c8e493b7f6c Mon Sep 17 00:00:00 2001 |
||||
From: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
Date: Fri, 3 Jun 2022 13:47:34 -0300 |
||||
Subject: [PATCH] Reduce the scope for SW usage on length threshold |
||||
|
||||
When compressing/decompressing large amounts of data, the first call to |
||||
deflate()/inflate() may not have data enough to pass the threshold, |
||||
causing libnxz to fallback to software prematurely. |
||||
We can only take that decision if the software indicates that all the |
||||
input has been made available, i.e. when flush == Z_FINISH. |
||||
|
||||
Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> |
||||
--- |
||||
lib/nx_deflate.c | 3 ++- |
||||
lib/nx_inflate.c | 3 ++- |
||||
lib/nx_zlib.h | 27 +++++++++++++++++++-------- |
||||
3 files changed, 23 insertions(+), 10 deletions(-) |
||||
|
||||
diff --git a/lib/nx_deflate.c b/lib/nx_deflate.c |
||||
index f2d5222..05b3580 100644 |
||||
--- a/lib/nx_deflate.c |
||||
+++ b/lib/nx_deflate.c |
||||
@@ -1534,7 +1534,8 @@ int nx_deflate(z_streamp strm, int flush) |
||||
return Z_STREAM_ERROR; |
||||
|
||||
/* check for sw deflate first */ |
||||
- if( (has_nx_state(strm)) && s->switchable && (0 == use_nx_deflate(strm))){ |
||||
+ if (has_nx_state(strm) && s->switchable |
||||
+ && (0 == use_nx_deflate(strm, flush))) { |
||||
/* Use software zlib, switch the sw and hw state */ |
||||
s = (nx_streamp) strm->state; |
||||
s->switchable = 0; /* decided to use sw zlib and not switchable */ |
||||
diff --git a/lib/nx_inflate.c b/lib/nx_inflate.c |
||||
index 6dac0ad..d59d5db 100644 |
||||
--- a/lib/nx_inflate.c |
||||
+++ b/lib/nx_inflate.c |
||||
@@ -289,7 +289,8 @@ int nx_inflate(z_streamp strm, int flush) |
||||
if (s == NULL) return Z_STREAM_ERROR; |
||||
|
||||
/* check for sw deflate first*/ |
||||
- if(has_nx_state(strm) && s->switchable && (0 == use_nx_inflate(strm))){ |
||||
+ if (has_nx_state(strm) && s->switchable |
||||
+ && (0 == use_nx_inflate(strm, flush))) { |
||||
/*Use software zlib, switch the sw and hw state*/ |
||||
s = (nx_streamp) strm->state; |
||||
s->switchable = 0; /* decided to use sw zlib and not switchable */ |
||||
diff --git a/lib/nx_zlib.h b/lib/nx_zlib.h |
||||
index 7550c65..2c0bdb5 100644 |
||||
--- a/lib/nx_zlib.h |
||||
+++ b/lib/nx_zlib.h |
||||
@@ -341,7 +341,7 @@ static inline int has_nx_state(z_streamp strm) |
||||
return (nx_state->magic1 == MAGIC1); |
||||
} |
||||
|
||||
-static inline int use_nx_inflate(z_streamp strm) |
||||
+static inline int use_nx_inflate(z_streamp strm, int flush) |
||||
{ |
||||
uint64_t rnd; |
||||
assert(strm != NULL); |
||||
@@ -349,8 +349,13 @@ static inline int use_nx_inflate(z_streamp strm) |
||||
if(nx_config.mode.inflate == GZIP_NX) return 1; |
||||
if(nx_config.mode.inflate == GZIP_SW) return 0; |
||||
|
||||
- /* #1 Threshold */ |
||||
- if(strm->avail_in <= DECOMPRESS_THRESHOLD) return 0; |
||||
+ /* #2 Length threshold |
||||
+ Even when decompressing a large amount of data, the first call to |
||||
+ inflate() may not have enough input. So, avoid switching to software |
||||
+ decompression prematurely unless there is a guarantee that all the |
||||
+ input has been provided, i.e. when using Z_FINISH. */ |
||||
+ if(flush == Z_FINISH && strm->avail_in <= DECOMPRESS_THRESHOLD) |
||||
+ return 0; |
||||
|
||||
if(nx_config.mode.inflate == GZIP_AUTO) return 1; |
||||
|
||||
@@ -363,15 +368,21 @@ static inline int use_nx_inflate(z_streamp strm) |
||||
} |
||||
} |
||||
|
||||
-static inline int use_nx_deflate(z_streamp strm) |
||||
+static inline int use_nx_deflate(z_streamp strm, int flush) |
||||
{ |
||||
assert(strm != NULL); |
||||
|
||||
- if(nx_config.mode.deflate == GZIP_NX) return 1; |
||||
- if(nx_config.mode.deflate == GZIP_SW) return 0; |
||||
+ if(nx_config.mode.deflate == GZIP_NX) return 1; |
||||
+ if(nx_config.mode.deflate == GZIP_SW) return 0; |
||||
+ |
||||
+ /* #2 Length threshold |
||||
+ Even when compressing a large amount of data, the first call to |
||||
+ deflate() may not have enough input. So, avoid switching to software |
||||
+ compression prematurely unless there is a guarantee that all the |
||||
+ input has been provided, i.e. when using Z_FINISH. */ |
||||
+ if(flush == Z_FINISH && strm->avail_in <= COMPRESS_THRESHOLD) |
||||
+ return 0; |
||||
|
||||
- /* #1 Threshold */ |
||||
- if(strm->avail_in <= COMPRESS_THRESHOLD) return 0; |
||||
return 1; |
||||
} |
||||
|
||||
-- |
||||
2.35.3 |
||||
|
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
# Keep the *.la file around |
||||
# See https://fedoraproject.org/wiki/Changes/RemoveLaFiles |
||||
%global __brp_remove_la_files %nil |
||||
|
||||
Name: libnxz |
||||
Version: 0.63 |
||||
Release: 4%{?dist} |
||||
Summary: Zlib implementation for POWER processors |
||||
License: ASL 2.0 or GPLv2+ |
||||
Url: https://github.com/libnxz/power-gzip |
||||
BuildRequires: zlib-devel |
||||
Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz |
||||
|
||||
# https://github.com/libnxz/power-gzip/pull/150 |
||||
Patch0: pr150.patch |
||||
# https://github.com/libnxz/power-gzip/pull/155 |
||||
Patch1: pr155.patch |
||||
# https://github.com/libnxz/power-gzip/pull/174 |
||||
Patch2: pr174.patch |
||||
|
||||
# Be explicit about the soname in order to avoid unintentional changes. |
||||
%global soname libnxz.so.0 |
||||
|
||||
ExclusiveArch: ppc64le |
||||
BuildRequires: gcc |
||||
BuildRequires: make |
||||
BuildRequires: systemd-rpm-macros |
||||
|
||||
# udev rules for nx-gzip dev |
||||
Requires: powerpc-utils-core > 1.3.10-2 |
||||
|
||||
%description |
||||
libnxz is a zlib-compatible library that uses the NX GZIP Engine available on |
||||
POWER9 or newer processors in order to provide a faster zlib/gzip compression |
||||
without using the general-purpose cores. |
||||
|
||||
%package devel |
||||
Summary: Development files for %{name} |
||||
Requires: %{name}%{?_isa} = %{version}-%{release} |
||||
|
||||
%description devel |
||||
The %{name}-devel package contains header files for developing application that |
||||
use %{name}. |
||||
|
||||
%package static |
||||
Summary: Static library for %{name} development |
||||
Requires: %{name}-devel%{?_isa} = %{version}-%{release} |
||||
|
||||
%description static |
||||
The %{name}-static package contains static libraries for developing |
||||
application that use %{name}. |
||||
|
||||
%prep |
||||
%autosetup -p1 -n power-gzip-%{version} |
||||
|
||||
%build |
||||
%configure --enable-zlib-api |
||||
%make_build |
||||
|
||||
%check |
||||
# libnxz tests only work on P9 servers or newer, with Linux >= 5.8. |
||||
# This combination is not guaranteed to have at build time. Check if |
||||
# NX GZIP engine device is available before deciding to run the tests. |
||||
if [[ -w "/dev/crypto/nx-gzip" ]]; then |
||||
make check |
||||
fi |
||||
|
||||
%install |
||||
%make_install |
||||
|
||||
%pre |
||||
%{_sbindir}/groupadd -r -f nx-gzip |
||||
|
||||
%files |
||||
%{_libdir}/%{soname} |
||||
%{_libdir}/libnxz.so.0.%{version} |
||||
%license %{_docdir}/%{name}/APACHE-2.0.txt |
||||
%license %{_docdir}/%{name}/gpl-2.0.txt |
||||
%doc README.md |
||||
|
||||
%files devel |
||||
%{_includedir}/libnxz.h |
||||
%{_libdir}/libnxz.so |
||||
|
||||
%files static |
||||
%{_libdir}/libnxz.a |
||||
%{_libdir}/libnxz.la |
||||
|
||||
%changelog |
||||
* Mon Jun 20 2022 Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> - 0.63-4 |
||||
- Fix an issue that caused premature fallback to software. |
||||
|
||||
* Tue Jun 14 2022 Jakub Čajka <jcajka@redhat.com> - 0.63-3 |
||||
- Move udev rule to the powerpc-utils-core |
||||
|
||||
* Thu Apr 14 2022 Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> - 0.63-2 |
||||
- Backport fixes from upstream. |
||||
- Create the nx-gzip group and add udev rules. |
||||
|
||||
* Fri Mar 04 2022 Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> - 0.63-1 |
||||
- Update to libnxz 0.63. |
||||
- Fix the soname to the right string. |
||||
- Properly list the dual-licensing scenario of the project. |
||||
|
||||
* Wed Jan 26 2022 Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com> - 0.62-4 |
||||
- Fix issue with GCC 12. |
||||
|
||||
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.62-3 |
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild |
||||
|
||||
* Fri Dec 03 2021 Tulio Magno Quites Machado Filho <tuliom@ascii.art.br> - 0.62-2 |
||||
- Enable tests if the NX GZIP engine is available. |
||||
|
||||
* Mon Aug 16 2021 Raphael Moreira Zinsly <rzinsly@linux.ibm.com> - 0.62-1 |
||||
- Update version. |
||||
|
||||
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.61-4 |
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild |
||||
|
||||
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.61-3 |
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild |
||||
|
||||
* Tue Nov 10 2020 Tulio Magno Quites Machado Filho <tuliom@ascii.art.br> - 0.61-2 |
||||
- Fix release version and match with changelog. |
||||
|
||||
* Tue Oct 27 2020 Tulio Magno Quites Machado Filho <tuliom@ascii.art.br> - 0.61-0 |
||||
- Initial packaging |
Loading…
Reference in new issue