зеркало из https://github.com/microsoft/StorScore.git
Improve control and reporting of overprovisioning. Added OP parameter to recipe, and calculation of OP to output spreadsheet. Fixed a bug so now partition size is reported correctly.
This commit is contained in:
Родитель
455cd074d1
Коммит
70aec20831
|
@ -2,4 +2,4 @@ The results in this directory were generated from
|
|||
the version of storscore published on the date listed
|
||||
below. If there is no date, the results were generated
|
||||
from an unpublished & untracked version of code.
|
||||
Tue 01/24/2017 9:00:53.83
|
||||
Mon 05/01/2017 9:25:23.74
|
||||
|
|
|
@ -138,11 +138,11 @@ has 'active_range' => (
|
|||
writer => '_active_range'
|
||||
);
|
||||
|
||||
has 'partition_bytes' => (
|
||||
has 'partition_bytes_override' => (
|
||||
is => 'ro',
|
||||
isa => 'Maybe[Int]',
|
||||
default => undef,
|
||||
writer => '_partition_bytes'
|
||||
writer => '_partition_bytes_override'
|
||||
);
|
||||
|
||||
has 'demo_mode' => (
|
||||
|
@ -155,7 +155,7 @@ has 'demo_mode' => (
|
|||
has 'auto_upload' => (
|
||||
is => 'ro',
|
||||
isa => 'Bool',
|
||||
default => 1,
|
||||
default => 0,
|
||||
writer => '_auto_upload'
|
||||
);
|
||||
|
||||
|
@ -279,7 +279,7 @@ sub BUILD
|
|||
"io_generator=s" => sub { $self->attr(@_) },
|
||||
"io_generator_args=s" => sub { $self->attr(@_) },
|
||||
"active_range=i" => sub { $self->attr(@_) },
|
||||
"partition_bytes=i" => sub { $self->attr(@_) },
|
||||
"partition_bytes_override=i" => sub { $self->attr(@_) },
|
||||
"demo_mode!" => sub { $self->attr(@_) },
|
||||
"auto_upload!" => sub { $self->attr(@_) },
|
||||
"results_share=s" => sub { $self->attr(@_) },
|
||||
|
@ -349,11 +349,11 @@ END
|
|||
warn $msg;
|
||||
}
|
||||
|
||||
if( defined $self->partition_bytes )
|
||||
if( defined $self->partition_bytes_override )
|
||||
{
|
||||
my $msg;
|
||||
|
||||
$msg .= "Ignoring --partition_bytes. ";
|
||||
$msg .= "Ignoring --partition_bytes_override. ";
|
||||
$msg .= "Not supported in raw disk mode.\n";
|
||||
|
||||
warn $msg;
|
||||
|
|
|
@ -54,6 +54,9 @@ sub compute_endurance($)
|
|||
|
||||
$stats_ref->{'Rated PE Cycles'} = $ddb_ref->{'Rated PE Cycles'};
|
||||
|
||||
compute_internal_capacity( $stats_ref, $ddb_ref );
|
||||
compute_OP( $stats_ref, $ddb_ref );
|
||||
|
||||
return unless test_contains_writes( $stats_ref );
|
||||
|
||||
compute_host_writes( $stats_ref, $ddb_ref );
|
||||
|
@ -190,21 +193,8 @@ sub compute_dwpd($$)
|
|||
|
||||
return unless $waf > 0;
|
||||
|
||||
my $internal_capacity = $ddb_ref->{'Internal Capacity'};
|
||||
|
||||
my $total_nand_bytes;
|
||||
|
||||
# If DeviceDB contains the actual internal capacity, use that.
|
||||
# Otherwise make a resonable assumption.
|
||||
if( defined $internal_capacity )
|
||||
{
|
||||
$total_nand_bytes = human_to_bytes( $internal_capacity );
|
||||
}
|
||||
else
|
||||
{
|
||||
$total_nand_bytes =
|
||||
round_up_power2( $stats_ref->{'User Capacity (B)'} );
|
||||
}
|
||||
my $total_nand_bytes = $stats_ref->{'Raw Capacity (GiB)'} *
|
||||
BYTES_PER_GB_BASE2;
|
||||
|
||||
# Give the drive credit for OP and TRIM'd space
|
||||
my $mapped_bytes = $stats_ref->{'Partition Size (B)'};
|
||||
|
@ -227,4 +217,47 @@ sub test_contains_writes($)
|
|||
return $stats_ref->{'W Mix'} > 0;
|
||||
}
|
||||
|
||||
sub compute_OP($$)
|
||||
{
|
||||
my $stats_ref = shift;
|
||||
my $ddb_ref = shift;
|
||||
|
||||
my $exposed_bytes =
|
||||
$stats_ref->{'Partition Size (GB)'} * BYTES_PER_GB_BASE10;
|
||||
|
||||
# NB: it's conventional to interpret the raw capacity in GB instead of
|
||||
# GiB. This is how a 512GB drive has "0% OP" and can still maintain an FTL.
|
||||
my $raw_bytes =
|
||||
$stats_ref->{'Raw Capacity (GiB)'} * BYTES_PER_GB_BASE10;
|
||||
|
||||
my $hidden_bytes = $raw_bytes - $exposed_bytes;
|
||||
|
||||
$stats_ref->{'Overprovisioning'} =
|
||||
( $hidden_bytes / $exposed_bytes ) * 100 // "Unavailable";
|
||||
}
|
||||
|
||||
sub compute_internal_capacity($$)
|
||||
{
|
||||
my $stats_ref = shift;
|
||||
my $ddb_ref = shift;
|
||||
|
||||
my $internal_capacity = $ddb_ref->{'Internal Capacity'};
|
||||
|
||||
my $total_nand_bytes;
|
||||
|
||||
# If DeviceDB contains the actual internal capacity, use that.
|
||||
# Otherwise make a resonable assumption.
|
||||
if( defined $internal_capacity )
|
||||
{
|
||||
$total_nand_bytes = human_to_bytes( $internal_capacity );
|
||||
}
|
||||
else
|
||||
{
|
||||
$total_nand_bytes =
|
||||
round_up_power2( $stats_ref->{'User Capacity (B)'} );
|
||||
}
|
||||
|
||||
$stats_ref->{'Raw Capacity (GiB)'} = $total_nand_bytes / BYTES_PER_GB_BASE2;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -583,7 +583,7 @@ sub get_test_macro_string
|
|||
$str .= q( purge() if $args{'purge'} // 1; )
|
||||
if $self->target->do_purge;
|
||||
|
||||
$str .= q( initialize() if $args{'initialize'} // 1; )
|
||||
$str .= q( initialize( %args ) if $args{'initialize'} // 1; )
|
||||
if $self->target->do_initialize;
|
||||
|
||||
$str .= q( precondition( %args ) if $args{'precondition'} // 1; )
|
||||
|
@ -694,12 +694,12 @@ sub get_announcement_message
|
|||
my $short_pattern =
|
||||
$step_ref->{'access_pattern'} eq "random" ? "rnd" : "seq";
|
||||
|
||||
$msg = sprintf( " %4s, %3s, %3d%% read, %3d%% wri, QD=%3d",
|
||||
$msg = sprintf( " %4s, %3s, %3d%% wri, QD=%3d, Used=%3d%%",
|
||||
$step_ref->{'block_size'},
|
||||
$short_pattern,
|
||||
$step_ref->{'read_percentage'},
|
||||
$step_ref->{'write_percentage'},
|
||||
$step_ref->{'queue_depth'}
|
||||
$step_ref->{'queue_depth'},
|
||||
$step_ref->{'percent_used'} // 100
|
||||
);
|
||||
}
|
||||
elsif( $step_ref->{'kind'} eq 'idle' )
|
||||
|
@ -788,6 +788,7 @@ sub run_step
|
|||
{
|
||||
$self->target->initialize(
|
||||
msg_prefix => $progress,
|
||||
test_ref => $step_ref
|
||||
);
|
||||
}
|
||||
elsif( $kind eq 'precondition' )
|
||||
|
@ -800,7 +801,7 @@ sub run_step
|
|||
}
|
||||
elsif( $kind eq 'test' )
|
||||
{
|
||||
$self->target->prepare()
|
||||
$self->target->prepare( $step_ref )
|
||||
unless $self->target->is_prepared();
|
||||
|
||||
unless( $pretend or $self->cmd_line->raw_disk )
|
||||
|
@ -810,6 +811,14 @@ sub run_step
|
|||
}
|
||||
|
||||
my $desc = $step_ref->{'description'};
|
||||
|
||||
# Record statistics about this volume
|
||||
my $wmic_runner = WmicRunner->new(
|
||||
target => $self->target,
|
||||
output_dir => $self->output_dir
|
||||
);
|
||||
|
||||
$wmic_runner->collect( "wmic-$desc.txt" );
|
||||
|
||||
# Record background activity, if any, during this test
|
||||
if( scalar @{$self->bg_processes} > 0 )
|
||||
|
@ -908,7 +917,7 @@ sub run_step
|
|||
#
|
||||
# Does this make sense in a general purpose exec (fg & bg)?
|
||||
|
||||
$self->target->prepare()
|
||||
$self->target->prepare( $step_ref )
|
||||
unless $self->target->is_prepared();
|
||||
|
||||
unless( $pretend )
|
||||
|
|
|
@ -366,17 +366,27 @@ sub purge
|
|||
$self->_is_prepared( 0 );
|
||||
}
|
||||
|
||||
sub prepare
|
||||
sub prepare($)
|
||||
{
|
||||
my $self = shift;
|
||||
my $test_ref = shift;
|
||||
|
||||
return if $self->is_prepared;
|
||||
|
||||
if( $self->do_create_new_filesystem )
|
||||
{
|
||||
my $partition_bytes;
|
||||
|
||||
$partition_bytes = ( $test_ref->{'percent_used'} / 100.0 ) *
|
||||
get_drive_size( $self->physical_drive )
|
||||
if defined $test_ref->{'percent_used'};
|
||||
|
||||
$partition_bytes = $self->cmd_line->partition_bytes_override
|
||||
if defined $self->cmd_line->partition_bytes_override;
|
||||
|
||||
create_filesystem(
|
||||
$self->physical_drive,
|
||||
$self->cmd_line->partition_bytes
|
||||
$partition_bytes
|
||||
);
|
||||
|
||||
$self->_volume( physical_drive_to_volume( $self->physical_drive ) );
|
||||
|
@ -473,11 +483,7 @@ sub initialize
|
|||
my $msg_prefix = $args{'msg_prefix'} // die;
|
||||
my $test_ref = $args{'test_ref'};
|
||||
|
||||
if( defined $test_ref )
|
||||
{
|
||||
# Future work: allow for custom init pattern
|
||||
...
|
||||
}
|
||||
# Future work: allow for custom init pattern
|
||||
|
||||
unless( $self->do_initialize )
|
||||
{
|
||||
|
@ -497,7 +503,7 @@ sub initialize
|
|||
return;
|
||||
}
|
||||
|
||||
$self->prepare() unless $self->is_prepared();
|
||||
$self->prepare( $test_ref ) unless $self->is_prepared();
|
||||
|
||||
$self->precondition_runner->write_num_passes(
|
||||
msg_prefix => $msg_prefix . "Initializing: ",
|
||||
|
@ -534,7 +540,7 @@ sub precondition
|
|||
return;
|
||||
}
|
||||
|
||||
$self->prepare() unless $self->is_prepared();
|
||||
$self->prepare( $test_ref ) unless $self->is_prepared();
|
||||
|
||||
$self->precondition_runner->run_to_steady_state(
|
||||
msg_prefix => $msg_prefix . "Preconditioning: ",
|
||||
|
|
|
@ -525,6 +525,11 @@ push @cols,
|
|||
# don't want 3rd parties to see these
|
||||
push @cols,
|
||||
(
|
||||
{ name => 'Raw Capacity (GiB)' },
|
||||
{
|
||||
name => 'Overprovisioning',
|
||||
format => '#.#%',
|
||||
},
|
||||
{
|
||||
name => 'Wear Range Before',
|
||||
format => '#.#',
|
||||
|
@ -682,6 +687,12 @@ sub parse_directories(@)
|
|||
$file_stats{'Test Description'} = $base_name;
|
||||
|
||||
generate_timestamp( $base_name, \%file_stats );
|
||||
|
||||
if( -e "wmic-$base_name.txt" )
|
||||
{
|
||||
my $wmic = WmicParser->new();
|
||||
$wmic->parse( \%file_stats, "wmic-$base_name.txt" );
|
||||
}
|
||||
|
||||
parse_warmup_file(
|
||||
"warmup-$base_name.txt",
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
# vim: set filetype=perl:
|
||||
|
||||
# StorScore
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a
|
||||
# copy of this software and associated documentation files (the "Software"),
|
||||
# to deal in the Software without restriction, including without limitation
|
||||
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
# and/or sell copies of the Software, and to permit persons to whom the
|
||||
# Software is furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
# DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
# These tests correspond to the requirements defined in the WCS SSD
|
||||
# Specification version 3.0
|
||||
|
||||
include 'write_impact_check.rcp';
|
||||
|
||||
test(
|
||||
description => "Random Reads",
|
||||
write_percentage => 0,
|
||||
access_pattern => 'random',
|
||||
block_size => '4K',
|
||||
queue_depth => 4,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Random Writes",
|
||||
write_percentage => 100,
|
||||
access_pattern => 'random',
|
||||
block_size => '4K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Random 4k Mix",
|
||||
write_percentage => 100,
|
||||
access_pattern => 'random',
|
||||
block_size => '4K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Random 8k Mix",
|
||||
write_percentage => 100,
|
||||
access_pattern => 'random',
|
||||
block_size => '8K',
|
||||
queue_depth => 1,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Sequential Reads",
|
||||
write_percentage => 0,
|
||||
access_pattern => 'sequential',
|
||||
block_size => '128K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Sequential Writes",
|
||||
write_percentage => 100,
|
||||
access_pattern => 'sequential',
|
||||
block_size => '128K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
|
||||
# 20% OP corresponds to 88.89% of user-visible capacity
|
||||
test(
|
||||
description => "Random Writes 20% OP",
|
||||
percent_used => 88.89,
|
||||
write_percentage => 100,
|
||||
access_pattern => 'random',
|
||||
block_size => '4K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
||||
|
||||
test(
|
||||
description => "Random Mix 20% OP",
|
||||
percent_used => 88.89,
|
||||
write_percentage => 100,
|
||||
access_pattern => 'random',
|
||||
block_size => '8K',
|
||||
queue_depth => 32,
|
||||
warmup_time => 60,
|
||||
run_time => 3600,
|
||||
);
|
Загрузка…
Ссылка в новой задаче