2
0
Fork 0
mirror of https://github.com/ii64/sonic.git synced 2026-06-21 00:46:43 +08:00
sonic/issue_test/pretouch_test.go
liu 6deed01a90
opt: reduce memory pool size (#302)
* fix: reduce state stack size

* fix types

* opt: shrink encoder stack size

* opt: reduce decoder stack size

* add bench.py loops

Co-authored-by: liuqiang <liuqiang.06@bytedance.com>
Co-authored-by: duanyi.aster <duanyi.aster@bytedance.com>
2022-10-28 16:40:14 +08:00

375 lines
No EOL
17 KiB
Go

/*
* Copyright 2021 ByteDance Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package issue_test
import (
`bytes`
`compress/gzip`
`encoding/json`
`io/ioutil`
`reflect`
`testing`
`time`
. `github.com/bytedance/sonic`
`github.com/bytedance/sonic/option`
`github.com/stretchr/testify/require`
)
var jsonData = func() string {
// Read and decompress the test data.
b, err := ioutil.ReadFile("../testdata/synthea_fhir.json.gz")
if err != nil {
panic(err)
}
zr, err := gzip.NewReader(bytes.NewReader(b))
if err != nil {
panic(err)
}
data, err := ioutil.ReadAll(zr)
if err != nil {
panic(err)
}
return string(data)
}()
type (
syntheaRoot struct {
Entry []struct {
FullURL string `json:"fullUrl"`
Request *struct {
Method string `json:"method"`
URL string `json:"url"`
} `json:"request"`
Resource *struct {
AbatementDateTime time.Time `json:"abatementDateTime"`
AchievementStatus syntheaCode `json:"achievementStatus"`
Active bool `json:"active"`
Activity []struct {
Detail *struct {
Code syntheaCode `json:"code"`
Location syntheaReference `json:"location"`
Status string `json:"status"`
} `json:"detail"`
} `json:"activity"`
Address []syntheaAddress `json:"address"`
Addresses []syntheaReference `json:"addresses"`
AuthoredOn time.Time `json:"authoredOn"`
BillablePeriod syntheaRange `json:"billablePeriod"`
BirthDate string `json:"birthDate"`
CareTeam []struct {
Provider syntheaReference `json:"provider"`
Reference string `json:"reference"`
Role syntheaCode `json:"role"`
Sequence int64 `json:"sequence"`
} `json:"careTeam"`
Category []syntheaCode `json:"category"`
Claim syntheaReference `json:"claim"`
Class syntheaCoding `json:"class"`
ClinicalStatus syntheaCode `json:"clinicalStatus"`
Code syntheaCode `json:"code"`
Communication []struct {
Language syntheaCode `json:"language"`
} `json:"communication"`
Component []struct {
Code syntheaCode `json:"code"`
ValueQuantity syntheaCoding `json:"valueQuantity"`
} `json:"component"`
Contained []struct {
Beneficiary syntheaReference `json:"beneficiary"`
ID string `json:"id"`
Intent string `json:"intent"`
Payor []syntheaReference `json:"payor"`
Performer []syntheaReference `json:"performer"`
Requester syntheaReference `json:"requester"`
ResourceType string `json:"resourceType"`
Status string `json:"status"`
Subject syntheaReference `json:"subject"`
Type syntheaCode `json:"type"`
} `json:"contained"`
Created time.Time `json:"created"`
DeceasedDateTime time.Time `json:"deceasedDateTime"`
Description syntheaCode `json:"description"`
Diagnosis []struct {
DiagnosisReference syntheaReference `json:"diagnosisReference"`
Sequence int64 `json:"sequence"`
Type []syntheaCode `json:"type"`
} `json:"diagnosis"`
DosageInstruction []struct {
AsNeededBoolean bool `json:"asNeededBoolean"`
DoseAndRate []struct {
DoseQuantity *struct {
Value float64 `json:"value"`
} `json:"doseQuantity"`
Type syntheaCode `json:"type"`
} `json:"doseAndRate"`
Sequence int64 `json:"sequence"`
Timing *struct {
Repeat *struct {
Frequency int64 `json:"frequency"`
Period float64 `json:"period"`
PeriodUnit string `json:"periodUnit"`
} `json:"repeat"`
} `json:"timing"`
} `json:"dosageInstruction"`
EffectiveDateTime time.Time `json:"effectiveDateTime"`
Encounter syntheaReference `json:"encounter"`
Extension []syntheaExtension `json:"extension"`
Gender string `json:"gender"`
Goal []syntheaReference `json:"goal"`
ID string `json:"id"`
Identifier []struct {
System string `json:"system"`
Type syntheaCode `json:"type"`
Use string `json:"use"`
Value string `json:"value"`
} `json:"identifier"`
Insurance []struct {
Coverage syntheaReference `json:"coverage"`
Focal bool `json:"focal"`
Sequence int64 `json:"sequence"`
} `json:"insurance"`
Insurer syntheaReference `json:"insurer"`
Intent string `json:"intent"`
Issued time.Time `json:"issued"`
Item []struct {
Adjudication []struct {
Amount syntheaCurrency `json:"amount"`
Category syntheaCode `json:"category"`
} `json:"adjudication"`
Category syntheaCode `json:"category"`
DiagnosisSequence []int64 `json:"diagnosisSequence"`
Encounter []syntheaReference `json:"encounter"`
InformationSequence []int64 `json:"informationSequence"`
LocationCodeableConcept syntheaCode `json:"locationCodeableConcept"`
Net syntheaCurrency `json:"net"`
ProcedureSequence []int64 `json:"procedureSequence"`
ProductOrService syntheaCode `json:"productOrService"`
Sequence int64 `json:"sequence"`
ServicedPeriod syntheaRange `json:"servicedPeriod"`
} `json:"item"`
LifecycleStatus string `json:"lifecycleStatus"`
ManagingOrganization []syntheaReference `json:"managingOrganization"`
MaritalStatus syntheaCode `json:"maritalStatus"`
MedicationCodeableConcept syntheaCode `json:"medicationCodeableConcept"`
MultipleBirthBoolean bool `json:"multipleBirthBoolean"`
Name json.RawMessage `json:"name"`
NumberOfInstances int64 `json:"numberOfInstances"`
NumberOfSeries int64 `json:"numberOfSeries"`
OccurrenceDateTime time.Time `json:"occurrenceDateTime"`
OnsetDateTime time.Time `json:"onsetDateTime"`
Outcome string `json:"outcome"`
Participant []struct {
Individual syntheaReference `json:"individual"`
Member syntheaReference `json:"member"`
Role []syntheaCode `json:"role"`
} `json:"participant"`
Patient syntheaReference `json:"patient"`
Payment *struct {
Amount syntheaCurrency `json:"amount"`
} `json:"payment"`
PerformedPeriod syntheaRange `json:"performedPeriod"`
Period syntheaRange `json:"period"`
Prescription syntheaReference `json:"prescription"`
PrimarySource bool `json:"primarySource"`
Priority syntheaCode `json:"priority"`
Procedure []struct {
ProcedureReference syntheaReference `json:"procedureReference"`
Sequence int64 `json:"sequence"`
} `json:"procedure"`
Provider syntheaReference `json:"provider"`
ReasonCode []syntheaCode `json:"reasonCode"`
ReasonReference []syntheaReference `json:"reasonReference"`
RecordedDate time.Time `json:"recordedDate"`
Referral syntheaReference `json:"referral"`
Requester syntheaReference `json:"requester"`
ResourceType string `json:"resourceType"`
Result []syntheaReference `json:"result"`
Series []struct {
BodySite syntheaCoding `json:"bodySite"`
Instance []struct {
Number int64 `json:"number"`
SopClass syntheaCoding `json:"sopClass"`
Title string `json:"title"`
UID string `json:"uid"`
} `json:"instance"`
Modality syntheaCoding `json:"modality"`
Number int64 `json:"number"`
NumberOfInstances int64 `json:"numberOfInstances"`
Started string `json:"started"`
UID string `json:"uid"`
} `json:"series"`
ServiceProvider syntheaReference `json:"serviceProvider"`
Started time.Time `json:"started"`
Status string `json:"status"`
Subject syntheaReference `json:"subject"`
SupportingInfo []struct {
Category syntheaCode `json:"category"`
Sequence int64 `json:"sequence"`
ValueReference syntheaReference `json:"valueReference"`
} `json:"supportingInfo"`
Telecom []map[string]string `json:"telecom"`
Text map[string]string `json:"text"`
Total json.RawMessage `json:"total"`
Type json.RawMessage `json:"type"`
Use string `json:"use"`
VaccineCode syntheaCode `json:"vaccineCode"`
ValueCodeableConcept syntheaCode `json:"valueCodeableConcept"`
ValueQuantity syntheaCoding `json:"valueQuantity"`
VerificationStatus syntheaCode `json:"verificationStatus"`
} `json:"resource"`
} `json:"entry"`
ResourceType string `json:"resourceType"`
Type string `json:"type"`
}
syntheaCode struct {
Coding []syntheaCoding `json:"coding"`
Text string `json:"text"`
}
syntheaCoding struct {
Code string `json:"code"`
Display string `json:"display"`
System string `json:"system"`
Unit string `json:"unit"`
Value float64 `json:"value"`
}
syntheaReference struct {
Display string `json:"display"`
Reference string `json:"reference"`
}
syntheaAddress struct {
City string `json:"city"`
Country string `json:"country"`
Extension []syntheaExtension `json:"extension"`
Line []string `json:"line"`
PostalCode string `json:"postalCode"`
State string `json:"state"`
}
syntheaExtension struct {
URL string `json:"url"`
ValueAddress syntheaAddress `json:"valueAddress"`
ValueCode string `json:"valueCode"`
ValueDecimal float64 `json:"valueDecimal"`
ValueString string `json:"valueString"`
Extension []syntheaExtension `json:"extension"`
}
syntheaRange struct {
End time.Time `json:"end"`
Start time.Time `json:"start"`
}
syntheaCurrency struct {
Currency string `json:"currency"`
Value float64 `json:"value"`
}
)
func TestPretouchSynteaRoot(t *testing.T) {
m := new(syntheaRoot)
s := time.Now()
println("start decoder pretouch:", s.UnixNano())
require.Nil(t, Pretouch(reflect.TypeOf(m), option.WithCompileMaxInlineDepth(2), option.WithCompileRecursiveDepth(20)))
e := time.Now()
println("end decoder pretouch:", e.UnixNano())
println("elapsed:", e.Sub(s).Milliseconds(), "ms")
s = time.Now()
println("start decode:", s.UnixNano())
require.Nil(t, UnmarshalString(jsonData, m))
e = time.Now()
println("end decode:", e.UnixNano())
d1 := e.Sub(s).Nanoseconds()
println("elapsed:", d1, "ns")
s = time.Now()
println("start decode:", s.UnixNano())
require.Nil(t, UnmarshalString(jsonData, m))
e = time.Now()
println("end decode:", e.UnixNano())
d2 := e.Sub(s).Nanoseconds()
println("elapsed:", d2, "ns")
if d1 > d2 * 20 {
t.Fatal("decoder pretouch not finish yet")
}
s = time.Now()
println("start decode:", s.UnixNano())
require.Nil(t, UnmarshalString(jsonData, m))
e = time.Now()
println("end decode:", e.UnixNano())
d5 := e.Sub(s).Nanoseconds()
println("elapsed:", d5, "ns")
if d2 > d5 * 10 {
t.Fatal("decoder pretouch not finish yet")
}
s = time.Now()
println("start encode 1:", s.UnixNano())
_, err := MarshalString(*m)
require.Nil(t, err)
e = time.Now()
println("end encode 1:", e.UnixNano())
d3 := e.Sub(s).Nanoseconds()
println("elapsed:", d3, "ns")
s = time.Now()
println("start encode 2:", s.UnixNano())
_, err = MarshalString(m)
require.Nil(t, err)
e = time.Now()
println("end encode 2:", e.UnixNano())
d4 := e.Sub(s).Nanoseconds()
println("elapsed:", d4, "ns")
// if d3 > d4 * 10 {
// t.Fatal("encoder pretouch not finish yet")
// }
s = time.Now()
println("start encode 3:", s.UnixNano())
_, err = MarshalString(m)
require.Nil(t, err)
e = time.Now()
println("end encode 3:", e.UnixNano())
d6 := e.Sub(s).Nanoseconds()
println("elapsed:", d6, "ns")
if d4 > d6 * 10 {
t.Fatal("encoder pretouch not finish yet")
}
}
func BenchmarkDecodeSynteaRoot(b *testing.B) {
m := new(syntheaRoot)
require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10)))
b.SetBytes(int64(len(jsonData)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = UnmarshalString(jsonData, m)
}
}
func BenchmarkEncodeSynteaRoot(b *testing.B) {
m := new(syntheaRoot)
require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10)))
require.Nil(b, UnmarshalString(jsonData, m))
b.SetBytes(int64(len(jsonData)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = MarshalString(m)
}
}