github.com/bytedance/sonic@v1.11.7-0.20240517092252-d2edb31b167b/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/bytedance/sonic`
    29      `github.com/bytedance/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  
   281  func TestPretouchSynteaRoot(t *testing.T) {
   282      m := new(syntheaRoot)
   283      s := time.Now()
   284      println("start decoder pretouch:", s.UnixNano())
   285      require.Nil(t, Pretouch(reflect.TypeOf(m), option.WithCompileMaxInlineDepth(2), option.WithCompileRecursiveDepth(20)))
   286      e := time.Now()
   287      println("end decoder pretouch:", e.UnixNano())
   288      println("elapsed:", e.Sub(s).Milliseconds(), "ms")
   289      
   290      s = time.Now()
   291      println("start decode:", s.UnixNano())
   292      require.Nil(t, UnmarshalString(jsonData, m))
   293      e = time.Now()
   294      println("end decode:", e.UnixNano())
   295      d1 := e.Sub(s).Nanoseconds()
   296      println("elapsed:", d1, "ns")
   297  
   298      s = time.Now()
   299      println("start decode:", s.UnixNano())
   300      require.Nil(t, UnmarshalString(jsonData, m))
   301      e = time.Now()
   302      println("end decode:", e.UnixNano())
   303      d2 := e.Sub(s).Nanoseconds()
   304      println("elapsed:", d2, "ns")
   305      if d1 > d2 * 20 {
   306          t.Fatal("decoder pretouch not finish yet")
   307      }
   308  
   309      s = time.Now()
   310      println("start decode:", s.UnixNano())
   311      require.Nil(t, UnmarshalString(jsonData, m))
   312      e = time.Now()
   313      println("end decode:", e.UnixNano())
   314      d5 := e.Sub(s).Nanoseconds()
   315      println("elapsed:", d5, "ns")
   316      if d2 > d5 * 10 {
   317          t.Fatal("decoder pretouch not finish yet")
   318      }
   319  
   320      s = time.Now()
   321      println("start encode 1:", s.UnixNano())
   322      _, err := MarshalString(*m)
   323      require.Nil(t, err)
   324      e = time.Now()
   325      println("end encode 1:", e.UnixNano())
   326      d3 := e.Sub(s).Nanoseconds()
   327      println("elapsed:", d3, "ns")
   328      
   329      s = time.Now()
   330      println("start encode 2:", s.UnixNano())
   331      _, err = MarshalString(m)
   332      require.Nil(t, err)
   333      e = time.Now()
   334      println("end encode 2:", e.UnixNano())
   335      d4 := e.Sub(s).Nanoseconds()
   336      println("elapsed:", d4, "ns")
   337      // if d3 > d4 * 10 {
   338      //     t.Fatal("encoder pretouch not finish yet")
   339      // }
   340  
   341      s = time.Now()
   342      println("start encode 3:", s.UnixNano())
   343      _, err = MarshalString(m)
   344      require.Nil(t, err)
   345      e = time.Now()
   346      println("end encode 3:", e.UnixNano())
   347      d6 := e.Sub(s).Nanoseconds()
   348      println("elapsed:", d6, "ns")
   349      if d4 > d6 * 10 {
   350          t.Fatal("encoder pretouch not finish yet")
   351      }
   352  }
   353  
   354  func BenchmarkDecodeSynteaRoot(b *testing.B) {
   355      m := new(syntheaRoot)
   356      require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10)))
   357  
   358      b.SetBytes(int64(len(jsonData)))
   359      b.ResetTimer()
   360      for i := 0; i < b.N; i++ {
   361          _ = UnmarshalString(jsonData, m)
   362      }
   363  }
   364  
   365  func BenchmarkEncodeSynteaRoot(b *testing.B) {
   366      m := new(syntheaRoot)
   367      require.Nil(b, Pretouch(reflect.TypeOf(m), option.WithCompileRecursiveDepth(10)))
   368      require.Nil(b, UnmarshalString(jsonData, m))
   369  
   370      b.SetBytes(int64(len(jsonData)))
   371      b.ResetTimer()
   372      for i := 0; i < b.N; i++ {
   373          _, _ = MarshalString(m)
   374      }
   375  }