2010-12-28 3 views
4

ECMAScript 런타임 용 JSON 코드를 연마하고 실험을하기로 결정했습니다. 다음 str 함수에는 4 개의 논리적 단계가 있습니다.이 단계를 함수로 분해하고 인라인으로 표시했습니다.인라인 수정자를 남용하고 있습니까?

and private str (state:StringifyState) (key:string) (holder:IObject) : IDynamic = 
    let inline fourth (value:IDynamic) = 
     match value.TypeCode with 
     | LanguageTypeCode.Null -> 
      state.environment.CreateString "null" :> IDynamic 
     | LanguageTypeCode.Boolean -> 
      let v = value :?> IBoolean 
      state.environment.CreateString (if v.BaseValue then "true" else "false") :> IDynamic 
     | LanguageTypeCode.String -> 
      let v = value :?> IString 
      state.environment.CreateString (quote v.BaseValue) :> IDynamic 
     | LanguageTypeCode.Number -> 
      let v = value :?> INumber 
      if not (Double.IsInfinity(v.BaseValue)) 
      then v.ConvertToString() :> IDynamic 
      else state.environment.CreateString "null" :> IDynamic 
     | LanguageTypeCode.Object -> 
      let v = value :?> IObject 
      let v = if v.Class = "Array" then ja state v else jo state v 
      state.environment.CreateString v :> IDynamic 
     | _ -> 
      state.environment.Undefined :> IDynamic 
    let inline third (value:IDynamic) = 
     match value.TypeCode with 
     | LanguageTypeCode.Object -> 
      let v = value :?> IObject 
      match v.Class with 
      | "Number" -> 
       fourth (v.ConvertToNumber()) 
      | "String" -> 
       fourth (v.ConvertToString()) 
      | "Boolean" -> 
       fourth (v.ConvertToBoolean()) 
      | _ -> 
       fourth value 
     | _ -> 
      fourth value 
    let inline second (value:IDynamic) = 
     match state.replacerFunction with 
     | :? ICallable as f -> 
      let args = state.environment.CreateArgs ([| state.environment.CreateString key :> IDynamic; value |]) 
      let value = f.Call (state.environment, holder :> IDynamic, args) 
      third value 
     | _ -> 
      third value 
    let inline first (value:IDynamic) = 
     match value with 
     | :? IObject as v -> 
      let toJSON = v.Get "toJSON" 
      match toJSON with 
      | :? ICallable as f -> 
       let args = state.environment.CreateArgs ([| state.environment.CreateString key :> IDynamic |]) 
       let value = f.Call (state.environment, value, args) 
       second value 
      | _ -> 
       second value 
     | _ -> 
      second value 
    first (holder.Get key) 

전체 최적화로 컴파일하고 반사경을 사용하여 결과 어셈블리를 열어 결과를 확인합니다.

[CompilationArgumentCounts(new int[] { 1, 1, 1 })] 
internal static IDynamic str(StringifyState state, string key, IObject holder) 
{ 
    IObject obj3; 
    ICallable callable; 
    ICallable callable2; 
    IArgs args; 
    IDynamic dynamic3; 
    IDynamic dynamic4; 
    ICallable callable3; 
    IDynamic dynamic5; 
    IBoolean flag; 
    IString str; 
    INumber number; 
    IObject obj4; 
    string str2; 
    INumber number2; 
    IObject obj5; 
    string str3; 
    IString str4; 
    IBoolean flag2; 
    IDynamic thisBinding = holder.Get(key); 
    IObject obj2 = thisBinding as IObject; 
    if (obj2 == null) 
    { 
     callable = [email protected] as ICallable; 
     if (callable == null) 
     { 
      switch (thisBinding.TypeCode) 
      { 
       case LanguageTypeCode.Object: 
        obj3 = (IObject) thisBinding; 
        str2 = obj3.Class; 
        if (!string.Equals(str2, "Number")) 
        { 
         if (string.Equals(str2, "String")) 
         { 
          dynamic3 = obj3.ConvertToString(); 
          switch (dynamic3.TypeCode) 
          { 
           case LanguageTypeCode.Null: 
            return (IDynamic) [email protected]("null"); 

           case LanguageTypeCode.Boolean: 
            flag = (IBoolean) dynamic3; 
            return (IDynamic) [email protected](!flag.BaseValue ? "false" : "true"); 

           case LanguageTypeCode.String: 
            str4 = (IString) dynamic3; 
            return (IDynamic) [email protected](quote(str4.BaseValue)); 

           case LanguageTypeCode.Number: 
            number = (INumber) dynamic3; 
            if (double.IsInfinity(number.BaseValue)) 
            { 
             return (IDynamic) [email protected]("null"); 
            } 
            return (IDynamic) number.ConvertToString(); 

    // ... I removed a large amount of code. 

    return (IDynamic) [email protected]; 
} 

분명히 inline 수식어는 꽤 리터럴입니다. 코드는 매우 거대하며 일부 예비 테스트는 매우 효율적입니다. 결과 어셈블리의 크기에 신경 쓰지 않으면 모든 함수를 인라인으로 던지십시오. inline의 사용이 적절한 지 알 수있는 지침은 무엇입니까? 가능한 경우 매번 성능을 측정하지 않아도되도록하고 싶습니다.

+0

"초안 F # 부품 설계 지침 (2010 년 8 월)"을 읽었습니까? http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/fsharp-component-design-guidelines.pdf –

+0

중복 가능성? : F #에서'inline' 사용 : http : // stackoverflow.com/questions/3754862/use-of-inline-in-f ?? –

+0

@Mitch - 가능한 한 내 질문이 원래 생각했던 것만 큼 소리가 나지 않을 수도 있지만 링크 된 것과 다른 초점이 있다고 느낍니다. – ChaosPandion

답변

4

성능 고려 사항에만 inline을 사용하는 경우 일반적인 성능 관련 조언이 모두 적용됩니다. 가장 중요한 것은 성능 목표를 설정하고 응용 프로그램을 핫스팟 용으로 프로파일 링하는 것입니다. 그런 다음 성능이 개선 될 것으로 판단 할만한 이유가있는 경우 inline을 사용하고 성능을 테스트하여 테스트합니다. F # 컴파일러가 생성하는 일리노이는 어쨌든 컴파일 된 JIT이므로, F # 코드에서 inline을 사용하지 않아도 IL에서 크기가 작은 함수가 컴파일시에 인라인 될 수 있습니다.

정적으로 해결 된 유형 변수 (예 : 멤버 제약 조건)를 사용하려는 경우에만 일반적으로 inline을 사용합니다.

+0

이것은 문자 그대로 내가 생각해 봤지만 다른 누군가가 내 입장을 꽤 굳게한다고 말하고 있습니다. 나는 약간의 충고로 다른 전문가를 얻는지를보기 위해 잠시 동안 대답을 선택하지 않을 것이다. – ChaosPandion

2

나는 KVB의 대답에 동의하지만, 여기에 자신의 모든 기능에 인라인을 던지는 것은 그들이 결과 어셈블리의 크기에 대한 관심이 없었어요 고려가 아닌 경우

에 두 가지 특정 이유가 있습니다.

  1. 명백한 경우는 인라인 익명 함수가 작동하지 않을 것입니다.

  2. 더 많은 인라인 (특히 큰 기능) -> 적은 (효과적으로) 코드가 캐시에 맞음 -> 프로그램이 느리게 작동합니다.

관련 문제