--mimepart_4d3ccade13674_1386598b1b02572
Content-Type: text/plain
Content-Transfer-Encoding: Quoted-printable
Content-Disposition: inline

Feature #4309: [ext/openssl] ASN1 performance enhancement
http://redmine.ruby-lang.org/issues/show/4309

Author: Martin Bosslet
Status: Open, Priority: Normal
Category: ext, Target version: 1.9.3

Hi all,

recently I noticed that the method static int ossl_asn1_default_tag(VALUE obj)

(in ossl_asn1.c) iterates through an internal array each time a default tag is to be looked up resulting in O(n) runtime
performance. I thought this to be the ideal situation for using a hash and so I added one with OpenSSL::ASN1Data subclasses cting as keys and the corresponding tags as values. I also did some profiling to see whether the constant lookup time made
some impact. I first ran a test encoding and parsing a certificate a couple of times and that's what I got:

Old code:
1.998611 seconds.
2.004065 seconds.
1.981882 seconds.
2.129491 seconds.
1.953846 seconds.
1.957313 seconds.
1.958523 seconds.
1.976004 seconds.
1.925835 seconds.
1.974381 seconds.

New code:
1.886169 seconds.
1.871291 seconds.
1.829164 seconds.
1.927687 seconds.
1.879508 seconds.
1.848399 seconds.
1.942286 seconds.
1.908133 seconds.
1.839384 seconds.
1.861159 seconds.

Not much, but I think the improvement is noticeable. Next I ran a "worst case scenario" for the old code.
I encoded and decoded a Sequence with 4 BMPString values, since BMPStringith tag 30 is at the end of he internal array. Here the performance gain was roughly 15%:

Old code worst case:
1.507455 seconds.
1.503871 seconds.
1.563551 seconds.
1.523261 seconds.
1.564125 seconds.
1.526295 seconds.
1.553073 seconds.
1.877483 seconds.
1.543568 seconds.
1.518273 seconds.

New code worst case:
1.347785 seconds.
1.359214 seconds.
1.389248 seconds.
1.466773 seconds.
1.350079 seconds.
1.406290 seconds.
1.393683 seconds.
1.368601 seconds.
1.350600 seconds.
1.373738 seconds

Please find attached the patch (including tests) that would add this improvement to Ruby trunk.

Best regards,
Martin

PS: I also changed the UNIVERSAL_TAG_NAME constant's name for OpenSSL::ASN1::EndOfContent from "EOC" to
"END_OF_CONTENT" because all other names are the uppercase versions of their corresponding classes, this
would have been the only exception to that rule. hen I also exported two methods, default_tag and default_tag_of_class, for the ASN1 module. I needed hem for something I'm currently working on. These latter changes are independent of the performance
improvement described above.


----------------------------------------
http://redmine.ruby-lang.org

--mimepart_4d3ccade13674_1386598b1b02572
Content-Type: text/x-patch; name=class_tag_map.diff
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename=class_tag_map.diff

ClByb3BlcnR5IGNoYW5nZXMgb246IHJ1YnkvZXh0L29wZW5zc2wKX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX19fX19fX19fX19fXwpNb2RpZmllZDogc3ZuOmlnbm9yZQogICAtIEdO
VW1ha2VmaWxlCk1ha2VmaWxlCmRlcApleHRjb25mLmgKbWttZi5sb2cKb3Bl
bnNzbC5hCmNvbmZ0ZXN0LmRTWU0KCiAgICsgR05VbWFrZWZpbGUKTWFrZWZp
bGUKZGVwCmV4dGNvbmYuaApta21mLmxvZwpvcGVuc3NsLmEKY29uZnRlc3Qu
ZFNZTQpvcGVuc3NsLnNvCgoKSW5kZXg6IHJ1YnkvZXh0L29wZW5zc2wvb3Nz
bF9hc24xLmMKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gcnVieS9leHQv
b3BlbnNzbC9vc3NsX2FzbjEuYwkocmV2aXNpb24gMzA2NDApCisrKyBydWJ5
L2V4dC9vcGVuc3NsL29zc2xfYXNuMS5jCSh3b3JraW5nIGNvcHkpCkBAIC00
NTQsNyArNDU0LDcgQEAKIH0gb3NzbF9hc24xX2luZm9fdDsKIAogc3RhdGlj
IG9zc2xfYXNuMV9pbmZvX3Qgb3NzbF9hc24xX2luZm9bXSA9IHsKLSAgICB7
ICJFT0MiLCAgICAgICAgICAgICAgICZjQVNOMUVuZE9mQ29udGVudCwgICAg
fSwgIC8qICAwICovCisgICAgeyAiRU5EX09GX0NPTlRFTlQiLCAgICAmY0FT
TjFFbmRPZkNvbnRlbnQsICAgIH0sICAvKiAgMCAqLwogICAgIHsgIkJPT0xF
QU4iLCAgICAgICAgICAgJmNBU04xQm9vbGVhbiwgICAgICAgICB9LCAgLyog
IDEgKi8KICAgICB7ICJJTlRFR0VSIiwgICAgICAgICAgICZjQVNOMUludGVn
ZXIsICAgICAgICAgfSwgIC8qICAyICovCiAgICAgeyAiQklUX1NUUklORyIs
ICAgICAgICAmY0FTTjFCaXRTdHJpbmcsICAgICAgIH0sICAvKiAgMyAqLwpA
QCAtNDg3LDEwICs0ODcsMzQgQEAKICAgICB7ICJCTVBTVFJJTkciLCAgICAg
ICAgICZjQVNOMUJNUFN0cmluZywgICAgICAgfSwgIC8qIDMwICovCiB9Owog
CisKKwogaW50IG9zc2xfYXNuMV9pbmZvX3NpemUgPSAoc2l6ZW9mKG9zc2xf
YXNuMV9pbmZvKS9zaXplb2Yob3NzbF9hc24xX2luZm9bMF0pKTsKIAorc3Rh
dGljIFZBTFVFIGNsYXNzX3RhZ19tYXA7CisKIHN0YXRpYyBpbnQgb3NzbF9h
c24xX2RlZmF1bHRfdGFnKFZBTFVFIG9iaik7CiAKK3N0YXRpYyBWQUxVRQor
b3NzbF9hc24xX2RlZmF1bHRfdGFnX2NsYXNzKFZBTFVFIHNlbGYsIFZBTFVF
IGtsYXNzKQoreworICAgIFZBTFVFIHRhZyA9IHJiX2hhc2hfbG9va3VwKGNs
YXNzX3RhZ19tYXAsIGtsYXNzKTsKKyAgICBpZiAodGFnICE9IFFuaWwpIHsK
KyAgICAgICAgcmV0dXJuIHRhZzsKKyAgICB9CisKKyAgICBvc3NsX3JhaXNl
KGVBU04xRXJyb3IsICJ1bml2ZXJzYWwgdGFnIGZvciAlcyBub3QgZm91bmQi
LAorCSAgICAgICByYl9jbGFzczJuYW1lKGtsYXNzKSk7CisKKyAgICByZXR1
cm4gUW5pbDsgLyogZHVtbXkgKi8KK30KKworc3RhdGljIFZBTFVFCitvc3Ns
X2FzbjFfZGVmYXVsdF90YWdfcHVibGljKFZBTFVFIHNlbGYsIFZBTFVFIG9i
aikKK3sKKyAgcmV0dXJuIElOVDJOVU0ob3NzbF9hc24xX2RlZmF1bHRfdGFn
KG9iaikpOworfQorCiBBU04xX1RZUEUqCiBvc3NsX2FzbjFfZ2V0X2FzbjF0
eXBlKFZBTFVFIG9iaikKIHsKQEAgLTU3MCwxNCArNTk0LDE1IEBACiBzdGF0
aWMgaW50CiBvc3NsX2FzbjFfZGVmYXVsdF90YWcoVkFMVUUgb2JqKQogewot
ICAgIGludCBpOworICAgIFZBTFVFIHRtcF9jbGFzcyA9IENMQVNTX09GKG9i
aik7CisgICAgd2hpbGUgKHRtcF9jbGFzcykgeworICAgICAgICBWQUxVRSB0
YWcgPSByYl9oYXNoX2xvb2t1cChjbGFzc190YWdfbWFwLCB0bXBfY2xhc3Mp
OworICAgICAgICBpZiAodGFnICE9IFFuaWwpIHsKKyAgICAgICAgICAgIHJl
dHVybiBOVU0ySU5UKHRhZyk7CisgICAgICAgIH0KKyAgICAgICAgdG1wX2Ns
YXNzID0gUkNMQVNTX1NVUEVSKHRtcF9jbGFzcyk7CisgICAgfQogCi0gICAg
Zm9yKGkgPSAwOyBpIDwgb3NzbF9hc24xX2luZm9fc2l6ZTsgaSsrKXsKLQlp
Zihvc3NsX2FzbjFfaW5mb1tpXS5rbGFzcyAmJgotCSAgIHJiX29ial9pc19r
aW5kX29mKG9iaiwgKm9zc2xfYXNuMV9pbmZvW2ldLmtsYXNzKSl7Ci0JICAg
IHJldHVybiBpOwotCX0KLSAgICB9CiAgICAgb3NzbF9yYWlzZShlQVNOMUVy
cm9yLCAidW5pdmVyc2FsIHRhZyBmb3IgJXMgbm90IGZvdW5kIiwKIAkgICAg
ICAgcmJfY2xhc3MybmFtZShDTEFTU19PRihvYmopKSk7CiAKQEAgLTg0MSw3
ICs4NjYsNyBAQAogICAgICAgICAgICAgb3NzbF9hc24xX3NldF9pbmZpbml0
ZV9sZW5ndGgoYXNuMWRhdGEsIFF0cnVlKTsKICAgICAgICAgZWxzZQogICAg
ICAgICAgICAgb3NzbF9hc24xX3NldF9pbmZpbml0ZV9sZW5ndGgoYXNuMWRh
dGEsIFFmYWxzZSk7Ci0gICAgICAgIAorCiAJcmJfYXJ5X3B1c2goYXJ5LCBh
c24xZGF0YSk7CiAJbGVuZ3RoIC09IGxlbjsKICAgICAgICAgaWYob25jZSkg
YnJlYWs7CkBAIC0xMTkwLDYgKzEyMTUsOCBAQAogICAgIHJiX2RlZmluZV9t
b2R1bGVfZnVuY3Rpb24obUFTTjEsICJ0cmF2ZXJzZSIsIG9zc2xfYXNuMV90
cmF2ZXJzZSwgMSk7CiAgICAgcmJfZGVmaW5lX21vZHVsZV9mdW5jdGlvbiht
QVNOMSwgImRlY29kZSIsIG9zc2xfYXNuMV9kZWNvZGUsIDEpOwogICAgIHJi
X2RlZmluZV9tb2R1bGVfZnVuY3Rpb24obUFTTjEsICJkZWNvZGVfYWxsIiwg
b3NzbF9hc24xX2RlY29kZV9hbGwsIDEpOworICAgIHJiX2RlZmluZV9tb2R1
bGVfZnVuY3Rpb24obUFTTjEsICJkZWZhdWx0X3RhZ19vZl9jbGFzcyIsIG9z
c2xfYXNuMV9kZWZhdWx0X3RhZ19jbGFzcywgMSk7CisgICAgcmJfZGVmaW5l
X21vZHVsZV9mdW5jdGlvbihtQVNOMSwgImRlZmF1bHRfdGFnIiwgb3NzbF9h
c24xX2RlZmF1bHRfdGFnX3B1YmxpYywgMSk7CiAgICAgYXJ5ID0gcmJfYXJ5
X25ldygpOwogICAgIHJiX2RlZmluZV9jb25zdChtQVNOMSwgIlVOSVZFUlNB
TF9UQUdfTkFNRSIsIGFyeSk7CiAgICAgZm9yKGkgPSAwOyBpIDwgb3NzbF9h
c24xX2luZm9fc2l6ZTsgaSsrKXsKQEAgLTEyNjAsNCArMTI4NywzMSBAQAog
ICAgIHJiX2F0dHIoY0FTTjFCaXRTdHJpbmcsIHJiX2ludGVybigidW51c2Vk
X2JpdHMiKSwgMSwgMSwgMCk7CiAKICAgICByYl9kZWZpbmVfbWV0aG9kKGNB
U04xRW5kT2ZDb250ZW50LCAiaW5pdGlhbGl6ZSIsIG9zc2xfYXNuMWVvY19p
bml0aWFsaXplLCAwKTsKKworICAgIGNsYXNzX3RhZ19tYXAgPSByYl9oYXNo
X25ldygpOworICAgIHJiX2hhc2hfYXNldChjbGFzc190YWdfbWFwLCBjQVNO
MUVuZE9mQ29udGVudCwgSU5UMk5VTSgwKSk7CisgICAgcmJfaGFzaF9hc2V0
KGNsYXNzX3RhZ19tYXAsIGNBU04xQm9vbGVhbiwgSU5UMk5VTSgxKSk7Cisg
ICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19tYXAsIGNBU04xSW50ZWdlciwg
SU5UMk5VTSgyKSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19tYXAs
IGNBU04xQml0U3RyaW5nLCBJTlQyTlVNKDMpKTsKKyAgICByYl9oYXNoX2Fz
ZXQoY2xhc3NfdGFnX21hcCwgY0FTTjFPY3RldFN0cmluZywgSU5UMk5VTSg0
KSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19tYXAsIGNBU04xTnVs
bCwgSU5UMk5VTSg1KSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19t
YXAsIGNBU04xT2JqZWN0SWQsIElOVDJOVU0oNikpOworICAgIHJiX2hhc2hf
YXNldChjbGFzc190YWdfbWFwLCBjQVNOMUVudW1lcmF0ZWQsIElOVDJOVU0o
MTApKTsKKyAgICByYl9oYXNoX2FzZXQoY2xhc3NfdGFnX21hcCwgY0FTTjFV
VEY4U3RyaW5nLCBJTlQyTlVNKDEyKSk7CisgICAgcmJfaGFzaF9hc2V0KGNs
YXNzX3RhZ19tYXAsIGNBU04xU2VxdWVuY2UsIElOVDJOVU0oMTYpKTsKKyAg
ICByYl9oYXNoX2FzZXQoY2xhc3NfdGFnX21hcCwgY0FTTjFTZXQsIElOVDJO
VU0oMTcpKTsKKyAgICByYl9oYXNoX2FzZXQoY2xhc3NfdGFnX21hcCwgY0FT
TjFOdW1lcmljU3RyaW5nLCBJTlQyTlVNKDE4KSk7CisgICAgcmJfaGFzaF9h
c2V0KGNsYXNzX3RhZ19tYXAsIGNBU04xUHJpbnRhYmxlU3RyaW5nLCBJTlQy
TlVNKDE5KSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19tYXAsIGNB
U04xVDYxU3RyaW5nLCBJTlQyTlVNKDIwKSk7CisgICAgcmJfaGFzaF9hc2V0
KGNsYXNzX3RhZ19tYXAsIGNBU04xVmlkZW90ZXhTdHJpbmcsIElOVDJOVU0o
MjEpKTsKKyAgICByYl9oYXNoX2FzZXQoY2xhc3NfdGFnX21hcCwgY0FTTjFJ
QTVTdHJpbmcsIElOVDJOVU0oMjIpKTsKKyAgICByYl9oYXNoX2FzZXQoY2xh
c3NfdGFnX21hcCwgY0FTTjFVVENUaW1lLCBJTlQyTlVNKDIzKSk7CisgICAg
cmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19tYXAsIGNBU04xR2VuZXJhbGl6ZWRU
aW1lLCBJTlQyTlVNKDI0KSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3Rh
Z19tYXAsIGNBU04xR3JhcGhpY1N0cmluZywgSU5UMk5VTSgyNSkpOworICAg
IHJiX2hhc2hfYXNldChjbGFzc190YWdfbWFwLCBjQVNOMUlTTzY0U3RyaW5n
LCBJTlQyTlVNKDI2KSk7CisgICAgcmJfaGFzaF9hc2V0KGNsYXNzX3RhZ19t
YXAsIGNBU04xR2VuZXJhbFN0cmluZywgSU5UMk5VTSgyNykpOworICAgIHJi
X2hhc2hfYXNldChjbGFzc190YWdfbWFwLCBjQVNOMVVuaXZlcnNhbFN0cmlu
ZywgSU5UMk5VTSgyOCkpOworICAgIHJiX2hhc2hfYXNldChjbGFzc190YWdf
bWFwLCBjQVNOMUJNUFN0cmluZywgSU5UMk5VTSgzMCkpOworCisgICAgcmJf
ZGVmaW5lX2NvbnN0KG1BU04xLCAiQ0xBU1NfVEFHX01BUCIsIGNsYXNzX3Rh
Z19tYXApOwogfQogCkluZGV4OiBydWJ5L3Rlc3Qvb3BlbnNzbC90ZXN0X2Fz
bjEucmIKPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PQotLS0gcnVieS90ZXN0L29w
ZW5zc2wvdGVzdF9hc24xLnJiCShyZXZpc2lvbiAzMDY0MCkKKysrIHJ1Ynkv
dGVzdC9vcGVuc3NsL3Rlc3RfYXNuMS5yYgkod29ya2luZyBjb3B5KQpAQCAt
NDMwLDQgKzQzMCwzNiBAQAogICAgIGVuZAogICBlbmQKICAgCisgIGRlZiB0
ZXN0X2RlZmF1bHRfdGFnX29mX2NsYXNzCisgICAgT3BlblNTTDo6QVNOMTo6
Q0xBU1NfVEFHX01BUC5lYWNoIGRvIHxrbGFzcywgdGFnfAorICAgICAgYXNz
ZXJ0X2VxdWFsKHRhZywgT3BlblNTTDo6QVNOMS5kZWZhdWx0X3RhZ19vZl9j
bGFzcyhrbGFzcykpCisgICAgZW5kCisgIGVuZAorICAKKyAgZGVmIHRlc3Rf
ZGVmYXVsdF90YWcKKyAgICBhc3NlcnRfZXF1YWwoMCwgT3BlblNTTDo6QVNO
MS5kZWZhdWx0X3RhZyhPcGVuU1NMOjpBU04xOjpFbmRPZkNvbnRlbnQubmV3
KSkgICAgCisgICAgYXNzZXJ0X2VxdWFsKDEsIE9wZW5TU0w6OkFTTjEuZGVm
YXVsdF90YWcoT3BlblNTTDo6QVNOMTo6Qm9vbGVhbi5uZXcodHJ1ZSkpKQor
ICAgIGFzc2VydF9lcXVhbCgyLCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFn
KE9wZW5TU0w6OkFTTjE6OkludGVnZXIubmV3KDEpKSkKKyAgICBhc3NlcnRf
ZXF1YWwoMywgT3BlblNTTDo6QVNOMS5kZWZhdWx0X3RhZyhPcGVuU1NMOjpB
U04xOjpCaXRTdHJpbmcubmV3KCJceDAxIikpKQorICAgIGFzc2VydF9lcXVh
bCg0LCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6OkFTTjE6
Ok9jdGV0U3RyaW5nLm5ldygiXHgwMSIpKSkgICAgCisgICAgYXNzZXJ0X2Vx
dWFsKDUsIE9wZW5TU0w6OkFTTjEuZGVmYXVsdF90YWcoT3BlblNTTDo6QVNO
MTo6TnVsbC5uZXcobmlsKSkpICAgIAorICAgIGFzc2VydF9lcXVhbCg2LCBP
cGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6OkFTTjE6Ok9iamVj
dElkLm5ldygiMS4yLjMuNC41IikpKSAgICAKKyAgICBhc3NlcnRfZXF1YWwo
MTAsIE9wZW5TU0w6OkFTTjEuZGVmYXVsdF90YWcoT3BlblNTTDo6QVNOMTo6
RW51bWVyYXRlZC5uZXcoMSkpKSAgICAKKyAgICBhc3NlcnRfZXF1YWwoMTIs
IE9wZW5TU0w6OkFTTjEuZGVmYXVsdF90YWcoT3BlblNTTDo6QVNOMTo6VVRG
OFN0cmluZy5uZXcoImEiKSkpIAorICAgIGFzc2VydF9lcXVhbCgxNiwgT3Bl
blNTTDo6QVNOMS5kZWZhdWx0X3RhZyhPcGVuU1NMOjpBU04xOjpTZXF1ZW5j
ZS5uZXcoW10pKSkgICAgCisgICAgYXNzZXJ0X2VxdWFsKDE3LCBPcGVuU1NM
OjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6OkFTTjE6OlNldC5uZXcoW10p
KSkgICAgCisgICAgYXNzZXJ0X2VxdWFsKDE4LCBPcGVuU1NMOjpBU04xLmRl
ZmF1bHRfdGFnKE9wZW5TU0w6OkFTTjE6Ok51bWVyaWNTdHJpbmcubmV3KCJh
IikpKQorICAgIGFzc2VydF9lcXVhbCgxOSwgT3BlblNTTDo6QVNOMS5kZWZh
dWx0X3RhZyhPcGVuU1NMOjpBU04xOjpQcmludGFibGVTdHJpbmcubmV3KCJh
IikpKQorICAgIGFzc2VydF9lcXVhbCgyMCwgT3BlblNTTDo6QVNOMS5kZWZh
dWx0X3RhZyhPcGVuU1NMOjpBU04xOjpUNjFTdHJpbmcubmV3KCJhIikpKQor
ICAgIGFzc2VydF9lcXVhbCgyMSwgT3BlblNTTDo6QVNOMS5kZWZhdWx0X3Rh
ZyhPcGVuU1NMOjpBU04xOjpWaWRlb3RleFN0cmluZy5uZXcoImEiKSkpCisg
ICAgYXNzZXJ0X2VxdWFsKDIyLCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFn
KE9wZW5TU0w6OkFTTjE6OklBNVN0cmluZy5uZXcoImEiKSkpCisgICAgYXNz
ZXJ0X2VxdWFsKDIzLCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5T
U0w6OkFTTjE6OlVUQ1RpbWUubmV3KFRpbWUubm93KSkpCisgICAgYXNzZXJ0
X2VxdWFsKDI0LCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6
OkFTTjE6OkdlbmVyYWxpemVkVGltZS5uZXcoVGltZS5ub3cpKSkKKyAgICBh
c3NlcnRfZXF1YWwoMjUsIE9wZW5TU0w6OkFTTjEuZGVmYXVsdF90YWcoT3Bl
blNTTDo6QVNOMTo6R3JhcGhpY1N0cmluZy5uZXcoImEiKSkpCisgICAgYXNz
ZXJ0X2VxdWFsKDI2LCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5T
U0w6OkFTTjE6OklTTzY0U3RyaW5nLm5ldygiYSIpKSkKKyAgICBhc3NlcnRf
ZXF1YWwoMjcsIE9wZW5TU0w6OkFTTjEuZGVmYXVsdF90YWcoT3BlblNTTDo6
QVNOMTo6R2VuZXJhbFN0cmluZy5uZXcoImEiKSkpCisgICAgYXNzZXJ0X2Vx
dWFsKDI4LCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6OkFT
TjE6OlVuaXZlcnNhbFN0cmluZy5uZXcoImEiKSkpCisgICAgYXNzZXJ0X2Vx
dWFsKDMwLCBPcGVuU1NMOjpBU04xLmRlZmF1bHRfdGFnKE9wZW5TU0w6OkFT
TjE6OkJNUFN0cmluZy5uZXcoImEiKSkpCisgIGVuZAorICAKIGVuZCBpZiBk
ZWZpbmVkPyhPcGVuU1NMKQo-mimepart_4d3ccade13674_1386598b1b02572--