Skip to content

Commit 252feab

Browse files
exrmetrics print disk size of part (#2424)
* Adding feature which allows the disk sizes of induvidual parts in a multipart EXR to be printed as one of the exrmetrics stats. The current method only works when no output file is specified because we use the write position of the dummy output stream to derive bytes written per part. Added flag to enable part size printout. Signed-off-by: Aries Moczar <arcmantis@protulae.com> * Improved help description. Appended to website/bin/exrmetrics.rst Signed-off-by: Aries Moczar <arcmantis@protulae.com> * Improved help message to be more clear. Modified parse() to report error when user attempts to use --part-disk-size and -o or vice versa in command. Added test in test_exrmetrics.py to verify json ouput for --part-disk-size. Signed-off-by: Aries Moczar <arcmantis@protulae.com> --------- Signed-off-by: Aries Moczar <arcmantis@protulae.com> Co-authored-by: Cary Phillips <cary@ilm.com>
1 parent 99d87b4 commit 252feab

5 files changed

Lines changed: 73 additions & 4 deletions

File tree

src/bin/exrmetrics/exrmetrics.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -764,11 +764,21 @@ writeFile (
764764
MultiPartOutputFile& out,
765765
vector<partData>& parts,
766766
fileMetrics& metrics,
767-
bool logPerformance)
767+
bool logPerformance,
768+
OStream* os = nullptr)
768769
{
769770
//
770771
// Call initialization functions, Read image from source.
771772
//
773+
774+
uint64_t lastPosition = 0;
775+
uint64_t currentPosition = 0;
776+
777+
if (os)
778+
{
779+
lastPosition = os->tellp();
780+
}
781+
772782
for (size_t p = 0; p < parts.size (); ++p)
773783
{
774784
string type = out.header (p).type ();
@@ -780,6 +790,7 @@ writeFile (
780790
outpart,
781791
parts[p].readBuf.scanlineBuf,
782792
logPerformance ? &metrics.stats[p].writePerf : nullptr);
793+
if (os) currentPosition = os->tellp();
783794
}
784795
else if (type == TILEDIMAGE)
785796
{
@@ -788,6 +799,7 @@ writeFile (
788799
outpart,
789800
parts[p].readBuf.tiledBuf,
790801
logPerformance ? &metrics.stats[p].writePerf : nullptr);
802+
if (os) currentPosition = os->tellp();
791803
}
792804
else if (type == DEEPSCANLINE)
793805
{
@@ -796,6 +808,7 @@ writeFile (
796808
outpart,
797809
parts[p].readBuf.deepbuf,
798810
logPerformance ? &metrics.stats[p].writePerf : nullptr);
811+
if (os) currentPosition = os->tellp();
799812
}
800813
else if (type == DEEPTILE)
801814
{
@@ -804,6 +817,13 @@ writeFile (
804817
outpart,
805818
parts[p].readBuf.deepbuf,
806819
logPerformance ? &metrics.stats[p].writePerf : nullptr);
820+
if (os) currentPosition = os->tellp();
821+
}
822+
823+
if (os)
824+
{
825+
metrics.stats[p].sizeOnDisk = currentPosition - lastPosition;
826+
lastPosition = currentPosition;
807827
}
808828
}
809829
}
@@ -1117,13 +1137,14 @@ exrmetrics (
11171137
{
11181138
out = new MultiPartOutputFile (
11191139
outFileName, outHeaders.data (), outHeaders.size ());
1140+
writeFile (*out, parts, metrics, true);
11201141
}
11211142
else
11221143
{
11231144
out = new MultiPartOutputFile (
11241145
ostream, outHeaders.data (), outHeaders.size ());
1146+
writeFile (*out, parts, metrics, true,&ostream);
11251147
}
1126-
writeFile (*out, parts, metrics, true);
11271148
delete out;
11281149

11291150
if (reread)

src/bin/exrmetrics/exrmetrics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct partStats
5555
countRereadPerf; // for deep only, time rereading the per-pixel sample count
5656
std::vector<double>
5757
rereadPerf; // for deep, times reading the sample count, otherwise times reading the entire data
58+
uint64_t sizeOnDisk = 0; // record compressed size of part on disk.
5859

5960
partSizeData sizeData;
6061
};

src/bin/exrmetrics/main.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ usageMessage (ostream& stream, const char* program_name, bool verbose = false)
8585
" --time list comma separated list of operations to report timing for.\n"
8686
" operations can be any of read,write,reread (use --time none for no timing)\n"
8787
" --no-size don't output size data\n"
88+
" --part-disk-size Output the on-disk size of the data portion of each part in a multipart EXR file\n"
89+
" (including chunk headers). File output (-o) is not supported when using this option\n"
8890
" --json print output as JSON dictionary (Default mode)\n"
8991
" --csv print output in csv mode. If passes>1, show median timing\n"
9092
" default is JSON mode\n"
@@ -116,6 +118,7 @@ struct options
116118
int passes = 1;
117119
int timing = TIME_READ | TIME_REREAD | TIME_WRITE;
118120
bool outputSizeData = true;
121+
bool outputPartSizeOnDisk = false;
119122
bool verbose = false;
120123
bool csv = false;
121124
std::vector<PixelMode> pixelModes;
@@ -196,6 +199,7 @@ printPartStats (
196199
const partStats& data,
197200
const string indent,
198201
int timing,
202+
bool partSize,
199203
bool raw,
200204
bool stats)
201205
{
@@ -236,6 +240,15 @@ printPartStats (
236240
out << indent << "\"re-read time\": ";
237241
printTiming (data.rereadPerf, out, raw, stats);
238242
}
243+
244+
if (partSize)
245+
{
246+
if (output) { out << ",\n"; }
247+
output = true;
248+
out << indent << "\"size on disk\": "
249+
<< data.sizeOnDisk
250+
<< "\n";
251+
}
239252
}
240253

241254
void
@@ -244,6 +257,7 @@ jsonStats (
244257
list<runData>& data,
245258
bool outputSizeData,
246259
int timing,
260+
bool partSize,
247261
bool raw,
248262
bool stats)
249263
{
@@ -370,7 +384,7 @@ jsonStats (
370384
{
371385
out << ",\n";
372386
printPartStats (
373-
out, run.metrics.totalStats, " ", timing, raw, stats);
387+
out, run.metrics.totalStats, " ", timing,false, raw, stats);
374388
}
375389
if (timing && run.metrics.stats.size () > 1)
376390
{
@@ -388,6 +402,7 @@ jsonStats (
388402
run.metrics.stats[part],
389403
" ",
390404
timing,
405+
partSize,
391406
raw,
392407
stats);
393408
out << "\n }";
@@ -546,6 +561,11 @@ main (int argc, char** argv)
546561
return 1;
547562
}
548563

564+
// we are only able to compute part disk size if no output file is specified,
565+
// causing memory output stream to be used and allowing us to measure data output.
566+
567+
bool showPartSizeOnDisk = opts.outputPartSizeOnDisk && !opts.outFile;
568+
549569
if (opts.timing || opts.outputSizeData)
550570
{
551571

@@ -556,7 +576,7 @@ main (int argc, char** argv)
556576
else
557577
{
558578
jsonStats (
559-
cout, data, opts.outputSizeData, opts.timing, true, true);
579+
cout, data, opts.outputSizeData, opts.timing,showPartSizeOnDisk, true, true);
560580
}
561581
}
562582

@@ -778,6 +798,12 @@ options::parse (int argc, char* argv[])
778798
cerr << "-o output filename can only be specified once\n";
779799
return 1;
780800
}
801+
if (outputPartSizeOnDisk)
802+
{
803+
cerr << "--part-disk-size cannot be used with file output (-o)\n";
804+
return 1;
805+
}
806+
781807
outFile = argv[i + 1];
782808
i += 2;
783809
}
@@ -870,6 +896,17 @@ options::parse (int argc, char* argv[])
870896
outputSizeData = false;
871897
i += 1;
872898
}
899+
else if (!strcmp (argv[i], "--part-disk-size"))
900+
{
901+
if (outFile)
902+
{
903+
cerr << "--part-disk-size cannot be used with file output (-o)\n";
904+
return 1;
905+
}
906+
907+
outputPartSizeOnDisk = true;
908+
i += 1;
909+
}
873910
else if (!strcmp (argv[i], "-i"))
874911
{
875912
if (i > argc - 2)

src/test/bin/test_exrmetrics.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,9 @@ def cleanup():
7272
data = json.loads(result.stdout)
7373
assert(len(data)==1),"\n Unexpected list size in JSON object"
7474

75+
# test --part-disk-size json output
76+
result = do_run ([exrmetrics, test_images["multipart"], "--part-disk-size"])
77+
data = json.loads(result.stdout)
78+
assert(len(data)==1),"\n Unexpected list size in JSON object"
79+
7580
print("success")

website/bin/exrmetrics.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ Options:
8181

8282
Don't output size data.
8383

84+
.. describe:: --part-disk-size
85+
86+
Output the on-disk size of the data portion of each part in a multipart EXR file (including chunk headers).
87+
Useful for determining compression impact on part data. File output (``-o``) is not supported when using this option.
88+
8489
.. describe:: --json
8590

8691
Print output as JSON dictionary (default).

0 commit comments

Comments
 (0)