【问题标题】:Timing issue on schema validation with JSchema使用 JSchema 进行模式验证的时间问题
【发布时间】:2016-03-14 16:13:27
【问题描述】:

我想使用模式验证 JArray 中的 json 对象。我的测试数组包含 >100000 个对象。在时序分析期间,我发现与数组中的第一个对象相比,验证最后一个对象的时间要长很多倍(>500 倍)。

这是我的测试代码的一部分:

      ...
      string schemaShapeObjectStr = @"{ 'type':'object',
                              '$schema': 'http://json-schema.org/draft-03/schema',
                              'required':false, 
                                  'properties':{ 
                                      'MyShapeObject': { 
                                          'type':'object', 'id': 'MyShapeObject', 'required':true, 
                                          'properties':{ 
                                              'id': {'type':'string', 'id': 'id', 'maxLength': 6,'required':true},
                                              'XY': {'type': 'array','minItems': 2,'maxItems': 2,'uniqueItems': false,'required':true,
                                                  'items': {'type': 'number','multipleOf': 0.001,'minimum': -10000,'maximum': 10000},
                                                  'additionalItems': false
                                              }
                                          }, 'additionalProperties':false 
                                      } 
                                  } 
                              }";
      ...

      JSchema schemaMoveOverTo = JSchema.Parse(schemaMoveOverToStr);

      JArray shapeArray = (JArray)shapes["shape"];

      Int32 counter = 0;

      JObject itemFast = (JObject)shapeArray.First();
      JObject itemSlow = (JObject)shapeArray.Last();

      sw1.Reset();
      sw1.Start();

      foreach (JObject item in shapeArray.Children<JObject>())
      {
          if (item.Properties().First().Name == "MyShapeObject")
          {
              counter++;
              stopwatch2.Reset();
              stopwatch2.Start();
              valid = itemFast.IsValid(schemaShapeObject, out messages);
              stopwatch2.Stop();
              calcTimeFast += stopwatch2.Elapsed;

              stopwatch2.Reset();
              stopwatch2.Start();
              valid = itemSlow.IsValid(schemaShapeObject, out messages);
              stopwatch2.Stop();
              calcTimeSlow += stopwatch2.Elapsed;
          }
      }
      sw1.Stop();
      meassureString = string.Format("loopThru Time = {0}, ShapeObject = {1}", sw1.Elapsed, counter);
      OutPutWindow.AppendText(meassureString + Environment.NewLine);
      meassureString = string.Format("Fast Time = {0}, Fast Mean = {1}, Slow Time = {2}, Slow Mean = {3}", calcTimeFast.TotalMilliseconds, (calcTimeFast.TotalMilliseconds / counter), calcTimeSlow.TotalMilliseconds, (calcTimeSlow.TotalMilliseconds / counter));
      OutPutWindow.AppendText(meassureString + Environment.NewLine);
    ...

我得到了这个输出:

loopThru Time = 00:06:36.1059322, ShapeObject = 89857
Fast Time = 628.6673, Fast Mean = 0.0069963085, Slow Time = 394959.2331, Slow Mean = 4.3954197569

对于我的测试,第一个和最后一个对象是相等的!

在另一个测试中我发现,模式验证时间随着数组中的位置连续增加...

谁能解释一下这种奇怪的行为。老实说,我是一名 C++ 开发人员,并且是 C# 的新手。在我看来,这两个 JObject(itemFast、itemSlow)是平等的,并且独立于它们的来源!?

我的代码有问题吗?

【问题讨论】:

    标签: c# json.net jsonschema


    【解决方案1】:

    为什么你从 shapeArray.Children&lt;JObject&gt;() 循环遍历结果然后从不使用它?

    itemFast 和 itemSlow 是同一个 JSON 吗?这可能解释了差异。如果没有,那么在某个地方上传一个带有 repo 的控制台项目,我会看看它。

    【讨论】:

    • 这只是一个测试。当我使用数组中的每个 JObject 时,测量的时间从第一个到最后一个增加。所以我改变了它,看看它是按计数增加还是按数组中的位置增加。答案似乎取决于数组中的位置。这是控制台项目的Link
    • JObject itemSlow = (JObject)shapeArray.Last().DeepClone(); //临时解决方法。这解决了性能问题。还不知道为什么。
    • 好的,我发现一个与验证包含许多项目的 JSON 数组中的项目相关的性能问题,这导致了您的问题。在验证之前对 JObject 调用 DeepClone 可以解决问题。库中会有一个修复,但大约一个月不会发布。
    猜你喜欢
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多