github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/issue_test/pretouch_test.go (about) 1 /* 2 * Copyright 2021 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package issue_test 18 19 import ( 20 "bytes" 21 "compress/gzip" 22 "encoding/json" 23 "io/ioutil" 24 "reflect" 25 "testing" 26 "time" 27 28 . "github.com/goshafaq/sonic" 29 "github.com/goshafaq/sonic/option" 30 "github.com/stretchr/testify/require" 31 ) 32 33 var jsonData = func() string { 34 // Read and decompress the test data. 35 b, err := ioutil.ReadFile("../testdata/synthea_fhir.json.gz") 36 if err != nil { 37 panic(err) 38 } 39 zr, err := gzip.NewReader(bytes.NewReader(b)) 40 if err != nil { 41 panic(err) 42 } 43 data, err := ioutil.ReadAll(zr) 44 if err != nil { 45 panic(err) 46 } 47 return string(data) 48 }() 49 50 type ( 51 syntheaRoot struct { 52 Entry []struct { 53 FullURL string `json:"fullUrl"` 54 Request *struct { 55 Method string `json:"method"` 56 URL string `json:"url"` 57 } `json:"request"` 58 Resource *struct { 59 AbatementDateTime time.Time `json:"abatementDateTime"` 60 AchievementStatus syntheaCode `json:"achievementStatus"` 61 Active bool `json:"active"` 62 Activity []struct { 63 Detail *struct { 64 Code syntheaCode `json:"code"` 65 Location syntheaReference `json:"location"` 66 Status string `json:"status"` 67 } `json:"detail"` 68 } `json:"activity"` 69 Address []syntheaAddress `json:"address"` 70 Addresses []syntheaReference `json:"addresses"` 71 AuthoredOn time.Time `json:"authoredOn"` 72 BillablePeriod syntheaRange `json:"billablePeriod"` 73 BirthDate string `json:"birthDate"` 74 CareTeam []struct { 75 Provider syntheaReference `json:"provider"` 76 Reference string `json:"reference"` 77 Role syntheaCode `json:"role"` 78 Sequence int64 `json:"sequence"` 79 } `json:"careTeam"` 80 Category []syntheaCode `json:"category"` 81 Claim syntheaReference `json:"claim"` 82 Class syntheaCoding `json:"class"` 83 ClinicalStatus syntheaCode `json:"clinicalStatus"` 84 Code syntheaCode `json:"code"` 85 Communication []struct { 86 Language syntheaCode `json:"language"` 87 } `json:"communication"` 88 Component []struct { 89 Code syntheaCode `json:"code"` 90 ValueQuantity syntheaCoding `json:"valueQuantity"` 91 } `json:"component"` 92 Contained []struct { 93 Beneficiary syntheaReference `json:"beneficiary"` 94 ID string `json:"id"` 95 Intent string `json:"intent"` 96 Payor []syntheaReference `json:"payor"` 97 Performer []syntheaReference `json:"performer"` 98 Requester syntheaReference `json:"requester"` 99 ResourceType string `json:"resourceType"` 100 Status string `json:"status"` 101 Subject syntheaReference `json:"subject"` 102 Type syntheaCode `json:"type"` 103 } `json:"contained"` 104 Created time.Time `json:"created"` 105 DeceasedDateTime time.Time `json:"deceasedDateTime"` 106 Description syntheaCode `json:"description"` 107 Diagnosis []struct { 108 DiagnosisReference syntheaReference `json:"diagnosisReference"` 109 Sequence int64 `json:"sequence"` 110 Type []syntheaCode `json:"type"` 111 } `json:"diagnosis"` 112 DosageInstruction []struct { 113 AsNeededBoolean bool `json:"asNeededBoolean"` 114 DoseAndRate []struct { 115 DoseQuantity *struct { 116 Value float64 `json:"value"` 117 } `json:"doseQuantity"` 118 Type syntheaCode `json:"type"` 119 } `json:"doseAndRate"` 120 Sequence int64 `json:"sequence"` 121 Timing *struct { 122 Repeat *struct { 123 Frequency int64 `json:"frequency"` 124 Period float64 `json:"period"` 125 PeriodUnit string `json:"periodUnit"` 126 } `json:"repeat"` 127 } `json:"timing"` 128 } `json:"dosageInstruction"` 129 EffectiveDateTime time.Time `json:"effectiveDateTime"` 130 Encounter syntheaReference `json:"encounter"` 131 Extension []syntheaExtension `json:"extension"` 132 Gender string `json:"gender"` 133 Goal []syntheaReference `json:"goal"` 134 ID string `json:"id"` 135 Identifier []struct { 136 System string `json:"system"` 137 Type syntheaCode `json:"type"` 138 Use string `json:"use"` 139 Value string `json:"value"` 140 } `json:"identifier"` 141 Insurance []struct { 142 Coverage syntheaReference `json:"coverage"` 143 Focal bool `json:"focal"` 144 Sequence int64 `json:"sequence"` 145 } `json:"insurance"` 146 Insurer syntheaReference `json:"insurer"` 147 Intent string `json:"intent"` 148 Issued time.Time `json:"issued"` 149 Item []struct { 150 Adjudication []struct { 151 Amount syntheaCurrency `json:"amount"` 152 Category syntheaCode `json:"category"` 153 } `json:"adjudication"` 154 Category syntheaCode `json:"category"` 155 DiagnosisSequence []int64 `json:"diagnosisSequence"` 156 Encounter []syntheaReference `json:"encounter"` 157 InformationSequence []int64 `json:"informationSequence"` 158 LocationCodeableConcept syntheaCode `json:"locationCodeableConcept"` 159 Net syntheaCurrency `json:"net"` 160 ProcedureSequence []int64 `json:"procedureSequence"` 161 ProductOrService syntheaCode `json:"productOrService"` 162 Sequence int64 `json:"sequence"` 163 ServicedPeriod syntheaRange `json:"servicedPeriod"` 164 } `json:"item"` 165 LifecycleStatus string `json:"lifecycleStatus"` 166 ManagingOrganization []syntheaReference `json:"managingOrganization"` 167 MaritalStatus syntheaCode `json:"maritalStatus"` 168 MedicationCodeableConcept syntheaCode `json:"medicationCodeableConcept"` 169 MultipleBirthBoolean bool `json:"multipleBirthBoolean"` 170 Name json.RawMessage `json:"name"` 171 NumberOfInstances int64 `json:"numberOfInstances"` 172 NumberOfSeries int64 `json:"numberOfSeries"` 173 OccurrenceDateTime time.Time `json:"occurrenceDateTime"` 174 OnsetDateTime time.Time `json:"onsetDateTime"` 175 Outcome string `json:"outcome"` 176 Participant []struct { 177 Individual syntheaReference `json:"individual"` 178 Member syntheaReference `json:"member"` 179 Role []syntheaCode `json:"role"` 180 } `json:"participant"` 181 Patient syntheaReference `json:"patient"` 182 Payment *struct { 183 Amount syntheaCurrency `json:"amount"` 184 } `json:"payment"` 185 PerformedPeriod syntheaRange `json:"performedPeriod"` 186 Period syntheaRange `json:"period"` 187 Prescription syntheaReference `json:"prescription"` 188 PrimarySource bool `json:"primarySource"` 189 Priority syntheaCode `json:"priority"` 190 Procedure []struct { 191 ProcedureReference syntheaReference `json:"procedureReference"` 192 Sequence int64 `json:"sequence"` 193 } `json:"procedure"` 194 Provider syntheaReference `json:"provider"` 195 ReasonCode []syntheaCode `json:"reasonCode"` 196 ReasonReference []syntheaReference `json:"reasonReference"` 197 RecordedDate time.Time `json:"recordedDate"` 198 Referral syntheaReference `json:"referral"` 199 Requester syntheaReference `json:"requester"` 200 ResourceType string `json:"resourceType"` 201 Result []syntheaReference `json:"result"` 202 Series []struct { 203 BodySite syntheaCoding `json:"bodySite"` 204 Instance []struct { 205 Number int64 `json:"number"` 206 SopClass syntheaCoding `json:"sopClass"` 207 Title string `json:"title"` 208 UID string `json:"uid"` 209 } `json:"instance"` 210 Modality syntheaCoding `json:"modality"` 211 Number int64 `json:"number"` 212 NumberOfInstances int64 `json:"numberOfInstances"` 213 Started string `json:"started"` 214 UID string `json:"uid"` 215 } `json:"series"` 216 ServiceProvider syntheaReference `json:"serviceProvider"` 217 Started time.Time `json:"started"` 218 Status string `json:"status"` 219 Subject syntheaReference `json:"subject"` 220 SupportingInfo []struct { 221 Category syntheaCode `json:"category"` 222 Sequence int64 `json:"sequence"` 223 ValueReference syntheaReference `json:"valueReference"` 224 } `json:"supportingInfo"` 225 Telecom []map[string]string `json:"telecom"` 226 Text map[string]string `json:"text"` 227 Total json.RawMessage `json:"total"` 228 Type json.RawMessage `json:"type"` 229 Use string `json:"use"` 230 VaccineCode syntheaCode `json:"vaccineCode"` 231 ValueCodeableConcept syntheaCode `json:"valueCodeableConcept"` 232 ValueQuantity syntheaCoding `json:"valueQuantity"` 233 VerificationStatus syntheaCode `json:"verificationStatus"` 234 } `json:"resource"` 235 } `json:"entry"` 236 ResourceType string `json:"resourceType"` 237 Type string `json:"type"` 238 } 239 syntheaCode struct { 240 Coding []syntheaCoding `json:"coding"` 241 Text string `json:"text"` 242 } 243 syntheaCoding struct { 244 Code string `json:"code"` 245 Display string `json:"display"` 246 System string `json:"system"` 247 Unit string `json:"unit"` 248 Value float64 `json:"value"` 249 } 250 syntheaReference struct { 251 Display string `json:"display"` 252 Reference string `json:"reference"` 253 } 254 syntheaAddress struct { 255 City string `json:"city"` 256 Country string `json:"country"` 257 Extension []syntheaExtension `json:"extension"` 258 Line []string `json:"line"` 259 PostalCode string `json:"postalCode"` 260 State string `json:"state"` 261 } 262 syntheaExtension struct { 263 URL string `json:"url"` 264 ValueAddress syntheaAddress `json:"valueAddress"` 265 ValueCode string `json:"valueCode"` 266 ValueDecimal float64 `json:"valueDecimal"` 267 ValueString string `json:"valueString"` 268 Extension []syntheaExtension `json:"extension"` 269 } 270 syntheaRange struct { 271 End time.Time `json:"end"` 272 Start time.Time `json:"start"` 273 } 274 syntheaCurrency struct { 275 Currency string `json:"currency"` 276 Value float64 `json:"value"` 277 } 278 ) 279 280 func TestPretouchSynteaRoot(t *testing.T) { 281 m := new(syntheaRoot) 282 s := time.Now() 283 println("start decoder pretouch:", s.UnixNano()) 284 require.Nil(t, Pretouch(reflect.TypeOf(m), option.WithCompileMaxInlineDepth(2), option.WithCompileRecursiveDepth(20))) 285 e := time.Now() 286 println("end decoder pretouch:", e.UnixNano()) 287 println("elapsed:", e.Sub(s).Milliseconds(), "ms") 288 289 s = time.Now() 290 println("start decode:", s.UnixNano()) 291 require.Nil(t, UnmarshalString(jsonData, m)) 292 e = time.Now() 293 println("end decode:", e.UnixNano()) 294 d1 := e.Sub(s).Nanoseconds() 295 println("elapsed:", d1, "ns") 296 297 s = time.Now() 298 println("start decode:", s.UnixNano()) 299 require.Nil(t, UnmarshalString(jsonData, m)) 300 e = time.Now() 301 println("end decode:", e.UnixNano()) 302 d2 := e.Sub(s).Nanoseconds() 303 println("elapsed:", d2, "ns") 304 if d1 > d2*20 { 305 t.Fatal("decoder pretouch not finish yet") 306 } 307 308 s = time.Now() 309 println("start decode:", s.UnixNano()) 310 require.Nil(t, UnmarshalString(jsonData, m)) 311 e = time.Now() 312 println("end decode:", e.UnixNano()) 313 d5 := e.Sub(s).Nanoseconds() 314 println("elapsed:", d5, "ns") 315 if d2 > d5*10 { 316 t.Fatal("decoder pretouch not finish yet") 317 } 318 319 s = time.Now() 320 println("start encode 1:", s.UnixNano()) 321 _, err := MarshalString(*m) 322 require.Nil(t, err) 323 e = time.Now() 324 println("end encode 1:", e.UnixNano()) 325 d3 := e.Sub(s).Nanoseconds() 326 println("elapsed:", d3, "ns") 327 328 s = time.Now() 329 println("start encode 2:", s.UnixNano()) 330 _, err = MarshalString(m) 331 require.Nil(t, err) 332 e = time.Now() 333 println("end encode 2:", e.UnixNano()) 334 d4 := e.Sub(s).Nanoseconds() 335 println("elapsed:", d4, "ns") 336 // if d3 > d4 * 10 { 337 // t.Fatal("encoder pretouch not finish yet") 338 // } 339 340 s = time.Now() 341 println("start encode 3:", s.UnixNano()) 342 _, err = MarshalString(m) 343 require.Nil(t, err) 344 e = time.Now() 345 println("end encode 3:", e.UnixNano()) 346 d6 := e.Sub(s).Nanoseconds() 347 println("elapsed:", d6, "ns") 348 if d4 > d6*10 { 349 t.Fatal("encoder pretouch not finish yet") 350 } 351 } 352 353 func BenchmarkDecodeSynteaRoot(b *testing.B) { 354 m := new(syntheaRoot) 355 require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10))) 356 357 b.SetBytes(int64(len(jsonData))) 358 b.ResetTimer() 359 for i := 0; i < b.N; i++ { 360 _ = UnmarshalString(jsonData, m) 361 } 362 } 363 364 func BenchmarkEncodeSynteaRoot(b *testing.B) { 365 m := new(syntheaRoot) 366 require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10))) 367 require.Nil(b, UnmarshalString(jsonData, m)) 368 369 b.SetBytes(int64(len(jsonData))) 370 b.ResetTimer() 371 for i := 0; i < b.N; i++ { 372 _, _ = MarshalString(m) 373 } 374 }