Index: service/datastore/properties.go |
diff --git a/service/datastore/properties.go b/service/datastore/properties.go |
index 9890a64c6aa3ce2ae7168f2f03e8b0447e10835b..60d8b423ad6dfc4fe7399a0570df4e7fbba883d8 100644 |
--- a/service/datastore/properties.go |
+++ b/service/datastore/properties.go |
@@ -588,6 +588,33 @@ func (s PropertySlice) Len() int { return len(s) } |
func (s PropertySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
func (s PropertySlice) Less(i, j int) bool { return s[i].Less(&s[j]) } |
+// EstimateSize estimates the amount of space that this Property would consume |
+// if it were committed as part of an entity in the real production datastore. |
+// |
+// It uses https://cloud.google.com/appengine/articles/storage_breakdown?csw=1 |
+// as a guide for these values. |
+func (p *Property) EstimateSize() int64 { |
+ switch p.Type() { |
+ case PTNull: |
+ return 1 |
+ case PTBool: |
+ return 1 + 4 |
+ case PTInt, PTTime, PTFloat: |
+ return 1 + 8 |
+ case PTGeoPoint: |
+ return 1 + (8 * 2) |
+ case PTString: |
+ return 1 + int64(len(p.value.(string))) |
+ case PTBlobKey: |
+ return 1 + int64(len(p.value.(blobstore.Key))) |
+ case PTBytes: |
+ return 1 + int64(len(p.value.([]byte))) |
+ case PTKey: |
+ return 1 + p.value.(*Key).EstimateSize() |
+ } |
+ panic(fmt.Errorf("Unknown property type: %s", p.Type().String())) |
+} |
+ |
// MetaGetter is a subinterface of PropertyLoadSaver, but is also used to |
// abstract the meta argument for RawInterface.GetMulti. |
type MetaGetter interface { |
@@ -767,6 +794,25 @@ func (pm PropertyMap) Problem() error { |
return nil |
} |
+// EstimateSize estimates the size that it would take to encode this PropertyMap |
+// in the production Appengine datastore. The calculation excludes metadata |
+// fields in the map. |
+// |
+// It uses https://cloud.google.com/appengine/articles/storage_breakdown?csw=1 |
+// as a guide for sizes. |
+func (pm PropertyMap) EstimateSize() int64 { |
+ ret := int64(0) |
+ for k, vals := range pm { |
+ if !isMetaKey(k) { |
+ ret += int64(len(k)) |
+ for i := range vals { |
+ ret += vals[i].EstimateSize() |
+ } |
+ } |
+ } |
+ return ret |
+} |
+ |
func isMetaKey(k string) bool { |
// empty counts as a metakey since it's not a valid data key, but it's |
// not really a valid metakey either. |