Fossil SCM

Merge the /artifact_size_stats page into the /artifact_stats page. Make that page accessible to anybody with check-in privilege.

drh 2017-12-11 14:52 trunk
Commit cefadbd5ce4dba55d73f5819cd224476d685d992dadab910559b283455c03720
2 files changed +4 +106 -93
+4
--- src/name.c
+++ src/name.c
@@ -1023,10 +1023,12 @@
10231023
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
10241024
style_header("List Of Artifacts");
10251025
style_submenu_element("250 Largest", "bigbloblist");
10261026
if( g.perm.Admin ){
10271027
style_submenu_element("Artifact Log", "rcvfromlist");
1028
+ }
1029
+ if( g.perm.Write ){
10281030
style_submenu_element("Artifact Stats", "artifact_stats");
10291031
}
10301032
if( !unpubOnly && mx>n && P("s")==0 ){
10311033
int i;
10321034
@ <p>Select a range of artifacts to view:</p>
@@ -1097,10 +1099,12 @@
10971099
10981100
login_check_credentials();
10991101
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
11001102
if( g.perm.Admin ){
11011103
style_submenu_element("Artifact Log", "rcvfromlist");
1104
+ }
1105
+ if( g.perm.Write ){
11021106
style_submenu_element("Artifact Stats", "artifact_stats");
11031107
}
11041108
style_submenu_element("All Artifacts", "bloblist");
11051109
style_header("%d Largest Artifacts", n);
11061110
db_multi_exec(
11071111
--- src/name.c
+++ src/name.c
@@ -1023,10 +1023,12 @@
1023 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1024 style_header("List Of Artifacts");
1025 style_submenu_element("250 Largest", "bigbloblist");
1026 if( g.perm.Admin ){
1027 style_submenu_element("Artifact Log", "rcvfromlist");
 
 
1028 style_submenu_element("Artifact Stats", "artifact_stats");
1029 }
1030 if( !unpubOnly && mx>n && P("s")==0 ){
1031 int i;
1032 @ <p>Select a range of artifacts to view:</p>
@@ -1097,10 +1099,12 @@
1097
1098 login_check_credentials();
1099 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1100 if( g.perm.Admin ){
1101 style_submenu_element("Artifact Log", "rcvfromlist");
 
 
1102 style_submenu_element("Artifact Stats", "artifact_stats");
1103 }
1104 style_submenu_element("All Artifacts", "bloblist");
1105 style_header("%d Largest Artifacts", n);
1106 db_multi_exec(
1107
--- src/name.c
+++ src/name.c
@@ -1023,10 +1023,12 @@
1023 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1024 style_header("List Of Artifacts");
1025 style_submenu_element("250 Largest", "bigbloblist");
1026 if( g.perm.Admin ){
1027 style_submenu_element("Artifact Log", "rcvfromlist");
1028 }
1029 if( g.perm.Write ){
1030 style_submenu_element("Artifact Stats", "artifact_stats");
1031 }
1032 if( !unpubOnly && mx>n && P("s")==0 ){
1033 int i;
1034 @ <p>Select a range of artifacts to view:</p>
@@ -1097,10 +1099,12 @@
1099
1100 login_check_credentials();
1101 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
1102 if( g.perm.Admin ){
1103 style_submenu_element("Artifact Log", "rcvfromlist");
1104 }
1105 if( g.perm.Write ){
1106 style_submenu_element("Artifact Stats", "artifact_stats");
1107 }
1108 style_submenu_element("All Artifacts", "bloblist");
1109 style_header("%d Largest Artifacts", n);
1110 db_multi_exec(
1111
+106 -93
--- src/stat.c
+++ src/stat.c
@@ -95,11 +95,11 @@
9595
if( !brief ){
9696
@ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
9797
n = db_int(0, "SELECT count(*) FROM blob");
9898
m = db_int(0, "SELECT count(*) FROM delta");
9999
@ %d(n) (%d(n-m) fulltext and %d(m) deltas)
100
- if( g.perm.Admin ){
100
+ if( g.perm.Write ){
101101
@ <a href='%R/artifact_stats'>Details</a>
102102
}
103103
@ </td></tr>
104104
if( n>0 ){
105105
int a, b;
@@ -575,10 +575,12 @@
575575
style_footer();
576576
}
577577
578578
/*
579579
** Gather statistics on artifact types, counts, and sizes.
580
+**
581
+** Only populate the artstat.atype field if the bWithTypes parameter is true.
580582
*/
581583
static void gather_artifact_stats(int bWithTypes){
582584
static const char zSql[] =
583585
@ CREATE TEMP TABLE artstat(
584586
@ id INTEGER PRIMARY KEY, -- Corresponds to BLOB.RID
@@ -637,66 +639,107 @@
637639
db_multi_exec("%s", zSql2/*safe-for-%s*/);
638640
}
639641
}
640642
641643
/*
642
-** WEBPAGE: artifact_size_stats
644
+** WEBPAGE: artifact_stats
643645
**
644
-** Show information about the sizes of artifacts.
646
+** Show information about the sizes of artifacts in this repository
645647
*/
646
-void artifact_size_stats_page(void){
648
+void artifact_stats_page(void){
647649
Stmt q;
648
- int nTotal = 0;
649
- int nDelta = 0;
650
- int nFull = 0;
650
+ int nTotal = 0; /* Total number of artifacts */
651
+ int nDelta = 0; /* Total number of deltas */
652
+ int nFull = 0; /* Total number of full-texts */
653
+ double avgCmpr = 0.0; /* Average size of an artifact after compression */
654
+ double avgExp = 0.0; /* Average size of an uncompressed artifact */
655
+ int mxCmpr = 0; /* Maximum compressed artifact size */
656
+ int mxExp = 0; /* Maximum uncompressed artifact size */
657
+ sqlite3_int64 sumCmpr = 0; /* Total size of all compressed artifacts */
658
+ sqlite3_int64 sumExp = 0; /* Total size of all expanded artifacts */
659
+ sqlite3_int64 sz1pct = 0; /* Space used by largest 1% */
660
+ sqlite3_int64 sz10pct = 0; /* Space used by largest 10% */
661
+ sqlite3_int64 sz25pct = 0; /* Space used by largest 25% */
662
+ sqlite3_int64 sz50pct = 0; /* Space used by largest 50% */
663
+ int n50pct = 0; /* Artifacts using the first 50% of space */
664
+ int n; /* Loop counter */
665
+ int medCmpr = 0; /* Median compressed artifact size */
666
+ int medExp = 0; /* Median expanded artifact size */
651667
int med;
652668
double r;
669
+
653670
login_check_credentials();
654
- if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
655
- style_header("Artifact Sizes");
656
- gather_artifact_stats(0);
657
- @ <table class="label-value">
671
+
672
+ /* These stats are expensive to compute. To disable them for
673
+ ** user without check-in privileges, to prevent excessive usage by
674
+ ** robots and random passers-by on the internet
675
+ */
676
+ if( !g.perm.Write ){
677
+ login_needed(g.anon.Admin);
678
+ return;
679
+ }
680
+
681
+ style_header("Artifact Statistics");
682
+ style_submenu_element("Repository Stats", "stat");
683
+ style_submenu_element("Artifact List", "bloblist");
684
+ gather_artifact_stats(1);
685
+
658686
db_prepare(&q,
659
- "SELECT count(*), sum(isDelta), avg(szCmpr), avg(szExp), max(szCmpr),"
660
- " max(szExp)"
687
+ "SELECT count(*), sum(isDelta), max(szCmpr),"
688
+ " max(szExp), sum(szCmpr), sum(szExp)"
661689
" FROM artstat"
662690
);
663
- if( db_step(&q)==SQLITE_ROW ){
664
- nTotal = db_column_int(&q,0);
665
- nDelta = db_column_int(&q,1);
666
- nFull = nTotal - nDelta;
667
- @ <tr><th>Number of artifacts:</th><td>%d(nTotal)</td></tr>
668
- if( nTotal>0 ){
669
- @ <tr><th>Number of deltas:</th>\
670
- @ <td>%d(nDelta) (%d(nDelta*100/nTotal)%%)</td></tr>
671
-
672
- @ <tr><th>Number of full-text:</th><td>%d(nFull) \
673
- @ (%d(nFull*100/nTotal)%%)</td></tr>
674
- }
675
- @ <tr><th>Largest compressed artifact size:</th>\
676
- @ <td>%d(db_column_int(&q,4))</td></tr>
677
-
678
- @ <tr><th>Average compressed artifact size:</th> \
679
- @ <td>%.2f(db_column_double(&q,2))</td></tr>
680
-
681
- db_multi_exec("CREATE INDEX artstatx1 ON artstat(szCmpr, isDelta);");
682
- med = db_int(0, "SELECT szCmpr FROM artstat ORDER BY szCmpr"
683
- " LIMIT 1 OFFSET %d", nTotal/2);
684
- @ <tr><th>Median compressed artifact size:</th><td>%d(med)</td></tr>
685
-
686
- @ <tr><th>Largest uncompressed artifact size:</td>\
687
- @ <td>%d(db_column_int(&q,5))</td></tr>
688
-
689
- @ <tr><th>Average uncompressed artifact size:</th> \
690
- @ <td>%.2f(db_column_double(&q,3))</td></tr>
691
-
692
- med = db_int(0, "SELECT szExp FROM artstat ORDER BY szExp"
693
- " LIMIT 1 OFFSET %d", nTotal/2);
694
- @ <tr><th>Median uncompressed artifact size:</th><td>%d(med)</td></tr>
695
-
691
+ db_step(&q);
692
+ nTotal = db_column_int(&q,0);
693
+ nDelta = db_column_int(&q,1);
694
+ nFull = nTotal - nDelta;
695
+ mxCmpr = db_column_int(&q, 2);
696
+ mxExp = db_column_int(&q, 3);
697
+ sumCmpr = db_column_int64(&q, 4);
698
+ sumExp = db_column_int64(&q, 5);
699
+ db_finalize(&q);
700
+ if( nTotal==0 ){
701
+ @ No artifacts in this repository!
702
+ style_footer();
703
+ return;
704
+ }
705
+ avgCmpr = (double)sumCmpr/nTotal;
706
+ avgExp = (double)sumExp/nTotal;
707
+
708
+ db_prepare(&q, "SELECT szCmpr FROM artstat ORDER BY 1 DESC");
709
+ r = 0;
710
+ n = 0;
711
+ while( db_step(&q)==SQLITE_ROW ){
712
+ r += db_column_int(&q, 0);
713
+ if( n50pct==0 && r>=sumCmpr/2 ) n50pct = n;
714
+ if( n==(nTotal+99)/100 ) sz1pct = r;
715
+ if( n==(nTotal+9)/10 ) sz10pct = r;
716
+ if( n==(nTotal+4)/5 ) sz25pct = r;
717
+ if( n==(nTotal+1)/2 ){ sz50pct = r; medCmpr = db_column_int(&q,0); }
718
+ n++;
696719
}
697720
db_finalize(&q);
721
+
722
+ @ <h1>Overall Artifact Size Statistics:</h1>
723
+ @ <table class="label-value">
724
+ @ <tr><th>Number of artifacts:</th><td>%d(nTotal)</td></tr>
725
+ @ <tr><th>Number of deltas:</th>\
726
+ @ <td>%d(nDelta) (%d(nDelta*100/nTotal)%%)</td></tr>
727
+ @ <tr><th>Number of full-text:</th><td>%d(nFull) \
728
+ @ (%d(nFull*100/nTotal)%%)</td></tr>
729
+ @ <tr><th>Largest compressed artifact size:</th>\
730
+ @ <td>%d(mxCmpr)</td></tr>
731
+ @ <tr><th>Average compressed artifact size:</th> \
732
+ @ <td>%.2f(avgCmpr)</td></tr>
733
+ @ <tr><th>Median compressed artifact size:</th><td>%d(medCmpr)</td></tr>
734
+ @ <tr><th>Largest uncompressed artifact size:</td>\
735
+ @ <td>%d(mxExp)</td></tr>
736
+ @ <tr><th>Average uncompressed artifact size:</th> \
737
+ @ <td>%.2f(avgExp)</td></tr>
738
+ medExp = db_int(0, "SELECT szExp FROM artstat ORDER BY szExp"
739
+ " LIMIT 1 OFFSET %d", nTotal/2);
740
+ @ <tr><th>Median uncompressed artifact size:</th><td>%d(medExp)</td></tr>
698741
db_prepare(&q,
699742
"SELECT avg(szCmpr), max(szCmpr) FROM artstat WHERE isDelta"
700743
);
701744
if( db_step(&q)==SQLITE_ROW ){
702745
@ <tr><th>Largest delta:</td>\
@@ -708,62 +751,32 @@
708751
med = db_int(0, "SELECT szCmpr FROM artstat WHERE isDelta ORDER BY szCmpr"
709752
" LIMIT 1 OFFSET %d", nDelta/2);
710753
@ <tr><th>Median delta:</th><td>%d(med)</td></tr>
711754
}
712755
db_finalize(&q);
713
-
714756
r = db_double(0.0, "SELECT avg(szCmpr) FROM artstat WHERE NOT isDelta;");
715757
@ <tr><th>Average full-text artifact:</th><td>%.2f(r)</td></tr>
716
-
717758
med = db_int(0, "SELECT szCmpr FROM artstat WHERE NOT isDelta ORDER BY szCmpr"
718759
" LIMIT 1 OFFSET %d", nFull/2);
719760
@ <tr><th>Median full-text artifact:</th><td>%d(med)</td></tr>
720761
@ </table>
721
- if( nTotal>0 ){
722
- sqlite3_int64 szTotal;
723
- sqlite3_int64 szPart;
724
- @ <h2>Artifact size distribution facts:</h2>
725
- @ <ol>
726
- szTotal = db_int64(0, "SELECT sum(szCmpr) FROM artstat");
727
- szPart = db_int64(0,
728
- "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
729
- " LIMIT %d)", (nTotal+99)/100);
730
- @ <li><p>The largest 1%% of artifacts (the largest %d((nTotal+99)/100) \
731
- @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
732
- szPart = db_int64(0,
733
- "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
734
- " LIMIT %d)", (nTotal+9)/10);
735
- @ <li><p>The largest 10%% of artifacts (the largest %d((nTotal+9)/10) \
736
- @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
737
- szPart = db_int64(0,
738
- "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
739
- " LIMIT %d)", nTotal/4);
740
- @ <li><p>The largest 25%% of artifacts (the largest %d(nTotal/4) \
741
- @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
742
- szPart = db_int64(0,
743
- "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
744
- " LIMIT %d)", nTotal/2);
745
- @ <li><p>The largest 50%% of artifacts (the largest %d(nTotal/2) \
746
- @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
747
- @ </ol>
748
- }
749
- style_footer();
750
-}
751
-
752
-/*
753
-** WEBPAGE: artifact_stats
754
-**
755
-** Show information about the sizes of artifacts in this repository
756
-*/
757
-void artifact_stats_page(void){
758
- Stmt q;
759
- login_check_credentials();
760
- if( !g.perm.Admin ){ login_needed(g.anon.Admin); return; }
761
- style_header("Artifact Statistics");
762
- style_submenu_element("Repository Stats", "stat");
763
- style_submenu_element("Artifact List", "bloblist");
764
- gather_artifact_stats(1);
762
+
763
+ @ <h1>Artifact size distribution facts:</h1>
764
+ @ <ol>
765
+ @ <li><p>The largest 1%% of artifacts (the largest %d((nTotal+99)/100) \
766
+ @ artifacts) use %lld(sz1pct*100/sumCmpr)%% of the total artifact space.
767
+ @ <li><p>The largest 10%% of artifacts (the largest %d((nTotal+9)/10) \
768
+ @ artifacts) use %lld(sz10pct*100/sumCmpr)%% of the total artifact space.
769
+ @ <li><p>The largest 25%% of artifacts (the largest %d(nTotal/4) \
770
+ @ artifacts) use %lld(sz25pct*100/sumCmpr)%% of the total artifact space.
771
+ @ <li><p>The largest 50%% of artifacts (the largest %d(nTotal/2) \
772
+ @ artifacts) use %lld(sz50pct*100/sumCmpr)%% of the total artifact space.
773
+ @ <li><p>Half of the total artifact space is used by the %d(n50pct) \
774
+ @ (%.1f(n50pct*100.0/nTotal)%%) largest artifacts.
775
+ @ </ol>
776
+
777
+ @ <h1>Artifact Sizes By Type:</h1>
765778
db_prepare(&q,
766779
"SELECT atype, count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
767780
" FROM artstat GROUP BY 1"
768781
" UNION ALL "
769782
"SELECT 'ALL', count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
@@ -812,11 +825,11 @@
812825
}
813826
@ </tbody></table>
814827
db_finalize(&q);
815828
816829
if( db_exists("SELECT 1 FROM artstat WHERE atype='unknown'") ){
817
- @ <h2>Unknown Artifacts</h2>
830
+ @ <h1>Unknown Artifacts:</h1>
818831
db_prepare(&q,
819832
"SELECT artstat.id, blob.uuid, user.login,"
820833
" datetime(rcvfrom.mtime), rcvfrom.rcvid"
821834
" FROM artstat JOIN blob ON artstat.id=blob.rid"
822835
" LEFT JOIN rcvfrom USING(rcvid)"
823836
--- src/stat.c
+++ src/stat.c
@@ -95,11 +95,11 @@
95 if( !brief ){
96 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
97 n = db_int(0, "SELECT count(*) FROM blob");
98 m = db_int(0, "SELECT count(*) FROM delta");
99 @ %d(n) (%d(n-m) fulltext and %d(m) deltas)
100 if( g.perm.Admin ){
101 @ <a href='%R/artifact_stats'>Details</a>
102 }
103 @ </td></tr>
104 if( n>0 ){
105 int a, b;
@@ -575,10 +575,12 @@
575 style_footer();
576 }
577
578 /*
579 ** Gather statistics on artifact types, counts, and sizes.
 
 
580 */
581 static void gather_artifact_stats(int bWithTypes){
582 static const char zSql[] =
583 @ CREATE TEMP TABLE artstat(
584 @ id INTEGER PRIMARY KEY, -- Corresponds to BLOB.RID
@@ -637,66 +639,107 @@
637 db_multi_exec("%s", zSql2/*safe-for-%s*/);
638 }
639 }
640
641 /*
642 ** WEBPAGE: artifact_size_stats
643 **
644 ** Show information about the sizes of artifacts.
645 */
646 void artifact_size_stats_page(void){
647 Stmt q;
648 int nTotal = 0;
649 int nDelta = 0;
650 int nFull = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651 int med;
652 double r;
 
653 login_check_credentials();
654 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
655 style_header("Artifact Sizes");
656 gather_artifact_stats(0);
657 @ <table class="label-value">
 
 
 
 
 
 
 
 
 
 
 
658 db_prepare(&q,
659 "SELECT count(*), sum(isDelta), avg(szCmpr), avg(szExp), max(szCmpr),"
660 " max(szExp)"
661 " FROM artstat"
662 );
663 if( db_step(&q)==SQLITE_ROW ){
664 nTotal = db_column_int(&q,0);
665 nDelta = db_column_int(&q,1);
666 nFull = nTotal - nDelta;
667 @ <tr><th>Number of artifacts:</th><td>%d(nTotal)</td></tr>
668 if( nTotal>0 ){
669 @ <tr><th>Number of deltas:</th>\
670 @ <td>%d(nDelta) (%d(nDelta*100/nTotal)%%)</td></tr>
671
672 @ <tr><th>Number of full-text:</th><td>%d(nFull) \
673 @ (%d(nFull*100/nTotal)%%)</td></tr>
674 }
675 @ <tr><th>Largest compressed artifact size:</th>\
676 @ <td>%d(db_column_int(&q,4))</td></tr>
677
678 @ <tr><th>Average compressed artifact size:</th> \
679 @ <td>%.2f(db_column_double(&q,2))</td></tr>
680
681 db_multi_exec("CREATE INDEX artstatx1 ON artstat(szCmpr, isDelta);");
682 med = db_int(0, "SELECT szCmpr FROM artstat ORDER BY szCmpr"
683 " LIMIT 1 OFFSET %d", nTotal/2);
684 @ <tr><th>Median compressed artifact size:</th><td>%d(med)</td></tr>
685
686 @ <tr><th>Largest uncompressed artifact size:</td>\
687 @ <td>%d(db_column_int(&q,5))</td></tr>
688
689 @ <tr><th>Average uncompressed artifact size:</th> \
690 @ <td>%.2f(db_column_double(&q,3))</td></tr>
691
692 med = db_int(0, "SELECT szExp FROM artstat ORDER BY szExp"
693 " LIMIT 1 OFFSET %d", nTotal/2);
694 @ <tr><th>Median uncompressed artifact size:</th><td>%d(med)</td></tr>
695
696 }
697 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
698 db_prepare(&q,
699 "SELECT avg(szCmpr), max(szCmpr) FROM artstat WHERE isDelta"
700 );
701 if( db_step(&q)==SQLITE_ROW ){
702 @ <tr><th>Largest delta:</td>\
@@ -708,62 +751,32 @@
708 med = db_int(0, "SELECT szCmpr FROM artstat WHERE isDelta ORDER BY szCmpr"
709 " LIMIT 1 OFFSET %d", nDelta/2);
710 @ <tr><th>Median delta:</th><td>%d(med)</td></tr>
711 }
712 db_finalize(&q);
713
714 r = db_double(0.0, "SELECT avg(szCmpr) FROM artstat WHERE NOT isDelta;");
715 @ <tr><th>Average full-text artifact:</th><td>%.2f(r)</td></tr>
716
717 med = db_int(0, "SELECT szCmpr FROM artstat WHERE NOT isDelta ORDER BY szCmpr"
718 " LIMIT 1 OFFSET %d", nFull/2);
719 @ <tr><th>Median full-text artifact:</th><td>%d(med)</td></tr>
720 @ </table>
721 if( nTotal>0 ){
722 sqlite3_int64 szTotal;
723 sqlite3_int64 szPart;
724 @ <h2>Artifact size distribution facts:</h2>
725 @ <ol>
726 szTotal = db_int64(0, "SELECT sum(szCmpr) FROM artstat");
727 szPart = db_int64(0,
728 "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
729 " LIMIT %d)", (nTotal+99)/100);
730 @ <li><p>The largest 1%% of artifacts (the largest %d((nTotal+99)/100) \
731 @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
732 szPart = db_int64(0,
733 "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
734 " LIMIT %d)", (nTotal+9)/10);
735 @ <li><p>The largest 10%% of artifacts (the largest %d((nTotal+9)/10) \
736 @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
737 szPart = db_int64(0,
738 "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
739 " LIMIT %d)", nTotal/4);
740 @ <li><p>The largest 25%% of artifacts (the largest %d(nTotal/4) \
741 @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
742 szPart = db_int64(0,
743 "SELECT sum(x) FROM (SELECT szCmpr AS x FROM artstat ORDER BY 1 DESC"
744 " LIMIT %d)", nTotal/2);
745 @ <li><p>The largest 50%% of artifacts (the largest %d(nTotal/2) \
746 @ artifacts) use %lld(szPart*100/szTotal)%% of the total artifact space.
747 @ </ol>
748 }
749 style_footer();
750 }
751
752 /*
753 ** WEBPAGE: artifact_stats
754 **
755 ** Show information about the sizes of artifacts in this repository
756 */
757 void artifact_stats_page(void){
758 Stmt q;
759 login_check_credentials();
760 if( !g.perm.Admin ){ login_needed(g.anon.Admin); return; }
761 style_header("Artifact Statistics");
762 style_submenu_element("Repository Stats", "stat");
763 style_submenu_element("Artifact List", "bloblist");
764 gather_artifact_stats(1);
765 db_prepare(&q,
766 "SELECT atype, count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
767 " FROM artstat GROUP BY 1"
768 " UNION ALL "
769 "SELECT 'ALL', count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
@@ -812,11 +825,11 @@
812 }
813 @ </tbody></table>
814 db_finalize(&q);
815
816 if( db_exists("SELECT 1 FROM artstat WHERE atype='unknown'") ){
817 @ <h2>Unknown Artifacts</h2>
818 db_prepare(&q,
819 "SELECT artstat.id, blob.uuid, user.login,"
820 " datetime(rcvfrom.mtime), rcvfrom.rcvid"
821 " FROM artstat JOIN blob ON artstat.id=blob.rid"
822 " LEFT JOIN rcvfrom USING(rcvid)"
823
--- src/stat.c
+++ src/stat.c
@@ -95,11 +95,11 @@
95 if( !brief ){
96 @ <tr><th>Number&nbsp;Of&nbsp;Artifacts:</th><td>
97 n = db_int(0, "SELECT count(*) FROM blob");
98 m = db_int(0, "SELECT count(*) FROM delta");
99 @ %d(n) (%d(n-m) fulltext and %d(m) deltas)
100 if( g.perm.Write ){
101 @ <a href='%R/artifact_stats'>Details</a>
102 }
103 @ </td></tr>
104 if( n>0 ){
105 int a, b;
@@ -575,10 +575,12 @@
575 style_footer();
576 }
577
578 /*
579 ** Gather statistics on artifact types, counts, and sizes.
580 **
581 ** Only populate the artstat.atype field if the bWithTypes parameter is true.
582 */
583 static void gather_artifact_stats(int bWithTypes){
584 static const char zSql[] =
585 @ CREATE TEMP TABLE artstat(
586 @ id INTEGER PRIMARY KEY, -- Corresponds to BLOB.RID
@@ -637,66 +639,107 @@
639 db_multi_exec("%s", zSql2/*safe-for-%s*/);
640 }
641 }
642
643 /*
644 ** WEBPAGE: artifact_stats
645 **
646 ** Show information about the sizes of artifacts in this repository
647 */
648 void artifact_stats_page(void){
649 Stmt q;
650 int nTotal = 0; /* Total number of artifacts */
651 int nDelta = 0; /* Total number of deltas */
652 int nFull = 0; /* Total number of full-texts */
653 double avgCmpr = 0.0; /* Average size of an artifact after compression */
654 double avgExp = 0.0; /* Average size of an uncompressed artifact */
655 int mxCmpr = 0; /* Maximum compressed artifact size */
656 int mxExp = 0; /* Maximum uncompressed artifact size */
657 sqlite3_int64 sumCmpr = 0; /* Total size of all compressed artifacts */
658 sqlite3_int64 sumExp = 0; /* Total size of all expanded artifacts */
659 sqlite3_int64 sz1pct = 0; /* Space used by largest 1% */
660 sqlite3_int64 sz10pct = 0; /* Space used by largest 10% */
661 sqlite3_int64 sz25pct = 0; /* Space used by largest 25% */
662 sqlite3_int64 sz50pct = 0; /* Space used by largest 50% */
663 int n50pct = 0; /* Artifacts using the first 50% of space */
664 int n; /* Loop counter */
665 int medCmpr = 0; /* Median compressed artifact size */
666 int medExp = 0; /* Median expanded artifact size */
667 int med;
668 double r;
669
670 login_check_credentials();
671
672 /* These stats are expensive to compute. To disable them for
673 ** user without check-in privileges, to prevent excessive usage by
674 ** robots and random passers-by on the internet
675 */
676 if( !g.perm.Write ){
677 login_needed(g.anon.Admin);
678 return;
679 }
680
681 style_header("Artifact Statistics");
682 style_submenu_element("Repository Stats", "stat");
683 style_submenu_element("Artifact List", "bloblist");
684 gather_artifact_stats(1);
685
686 db_prepare(&q,
687 "SELECT count(*), sum(isDelta), max(szCmpr),"
688 " max(szExp), sum(szCmpr), sum(szExp)"
689 " FROM artstat"
690 );
691 db_step(&q);
692 nTotal = db_column_int(&q,0);
693 nDelta = db_column_int(&q,1);
694 nFull = nTotal - nDelta;
695 mxCmpr = db_column_int(&q, 2);
696 mxExp = db_column_int(&q, 3);
697 sumCmpr = db_column_int64(&q, 4);
698 sumExp = db_column_int64(&q, 5);
699 db_finalize(&q);
700 if( nTotal==0 ){
701 @ No artifacts in this repository!
702 style_footer();
703 return;
704 }
705 avgCmpr = (double)sumCmpr/nTotal;
706 avgExp = (double)sumExp/nTotal;
707
708 db_prepare(&q, "SELECT szCmpr FROM artstat ORDER BY 1 DESC");
709 r = 0;
710 n = 0;
711 while( db_step(&q)==SQLITE_ROW ){
712 r += db_column_int(&q, 0);
713 if( n50pct==0 && r>=sumCmpr/2 ) n50pct = n;
714 if( n==(nTotal+99)/100 ) sz1pct = r;
715 if( n==(nTotal+9)/10 ) sz10pct = r;
716 if( n==(nTotal+4)/5 ) sz25pct = r;
717 if( n==(nTotal+1)/2 ){ sz50pct = r; medCmpr = db_column_int(&q,0); }
718 n++;
 
 
 
 
 
719 }
720 db_finalize(&q);
721
722 @ <h1>Overall Artifact Size Statistics:</h1>
723 @ <table class="label-value">
724 @ <tr><th>Number of artifacts:</th><td>%d(nTotal)</td></tr>
725 @ <tr><th>Number of deltas:</th>\
726 @ <td>%d(nDelta) (%d(nDelta*100/nTotal)%%)</td></tr>
727 @ <tr><th>Number of full-text:</th><td>%d(nFull) \
728 @ (%d(nFull*100/nTotal)%%)</td></tr>
729 @ <tr><th>Largest compressed artifact size:</th>\
730 @ <td>%d(mxCmpr)</td></tr>
731 @ <tr><th>Average compressed artifact size:</th> \
732 @ <td>%.2f(avgCmpr)</td></tr>
733 @ <tr><th>Median compressed artifact size:</th><td>%d(medCmpr)</td></tr>
734 @ <tr><th>Largest uncompressed artifact size:</td>\
735 @ <td>%d(mxExp)</td></tr>
736 @ <tr><th>Average uncompressed artifact size:</th> \
737 @ <td>%.2f(avgExp)</td></tr>
738 medExp = db_int(0, "SELECT szExp FROM artstat ORDER BY szExp"
739 " LIMIT 1 OFFSET %d", nTotal/2);
740 @ <tr><th>Median uncompressed artifact size:</th><td>%d(medExp)</td></tr>
741 db_prepare(&q,
742 "SELECT avg(szCmpr), max(szCmpr) FROM artstat WHERE isDelta"
743 );
744 if( db_step(&q)==SQLITE_ROW ){
745 @ <tr><th>Largest delta:</td>\
@@ -708,62 +751,32 @@
751 med = db_int(0, "SELECT szCmpr FROM artstat WHERE isDelta ORDER BY szCmpr"
752 " LIMIT 1 OFFSET %d", nDelta/2);
753 @ <tr><th>Median delta:</th><td>%d(med)</td></tr>
754 }
755 db_finalize(&q);
 
756 r = db_double(0.0, "SELECT avg(szCmpr) FROM artstat WHERE NOT isDelta;");
757 @ <tr><th>Average full-text artifact:</th><td>%.2f(r)</td></tr>
 
758 med = db_int(0, "SELECT szCmpr FROM artstat WHERE NOT isDelta ORDER BY szCmpr"
759 " LIMIT 1 OFFSET %d", nFull/2);
760 @ <tr><th>Median full-text artifact:</th><td>%d(med)</td></tr>
761 @ </table>
762
763 @ <h1>Artifact size distribution facts:</h1>
764 @ <ol>
765 @ <li><p>The largest 1%% of artifacts (the largest %d((nTotal+99)/100) \
766 @ artifacts) use %lld(sz1pct*100/sumCmpr)%% of the total artifact space.
767 @ <li><p>The largest 10%% of artifacts (the largest %d((nTotal+9)/10) \
768 @ artifacts) use %lld(sz10pct*100/sumCmpr)%% of the total artifact space.
769 @ <li><p>The largest 25%% of artifacts (the largest %d(nTotal/4) \
770 @ artifacts) use %lld(sz25pct*100/sumCmpr)%% of the total artifact space.
771 @ <li><p>The largest 50%% of artifacts (the largest %d(nTotal/2) \
772 @ artifacts) use %lld(sz50pct*100/sumCmpr)%% of the total artifact space.
773 @ <li><p>Half of the total artifact space is used by the %d(n50pct) \
774 @ (%.1f(n50pct*100.0/nTotal)%%) largest artifacts.
775 @ </ol>
776
777 @ <h1>Artifact Sizes By Type:</h1>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778 db_prepare(&q,
779 "SELECT atype, count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
780 " FROM artstat GROUP BY 1"
781 " UNION ALL "
782 "SELECT 'ALL', count(*), sum(isDelta), sum(szCmpr), sum(szExp)"
@@ -812,11 +825,11 @@
825 }
826 @ </tbody></table>
827 db_finalize(&q);
828
829 if( db_exists("SELECT 1 FROM artstat WHERE atype='unknown'") ){
830 @ <h1>Unknown Artifacts:</h1>
831 db_prepare(&q,
832 "SELECT artstat.id, blob.uuid, user.login,"
833 " datetime(rcvfrom.mtime), rcvfrom.rcvid"
834 " FROM artstat JOIN blob ON artstat.id=blob.rid"
835 " LEFT JOIN rcvfrom USING(rcvid)"
836

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button