저희 커플이 결혼 준비하면서

가장 먼저 한일은 웨딩박람회 방문이였습니다.

 

 

비록 소박람회였지만

많은 걸 알아볼 수 있어서 좋았습니다~

 

 

박람회에서 스드메 계약하고

오르시아에서 상담받으면서

혜택이 정말 좋은거 같아 가계약을 하고 왔었습니다.

 

그 후 플래너를 통해 예약하고

방문했네요

똑똑

 

 

우리 플래너님이 오르시아에서

사장님 다음으로 높으신 분에게 예약을

해주셨어용

슈퍼맨

 

 

예물을 보러

예랑이와 함께 오르시아로 향했습니다

 

강남구청역 3번 출구로 나오면 바로 코앞이라

찾기 정말 쉬운거 같아요

 

전쟁떡볶이 골목으로 들어가면

오르시아 간판이 바로 보여요

 

 

 

바로 저 건물 5층이

오르시아에요 ㅋㅋ

 

5층으로 올라가면

 금빛 글씨로 orsia jewelry라고

쓰여있답니다.

 

 

처음 보자마자 금이 마구마구 생각났네요..ㅋㅋㅋ

 

왼쪽엔 화장실이 있고

오른쪽으로 보면 문이

잠겨있는 입구가 보입니다. 

 

보안을 철저하게 유지하는게 느껴지죠??

 

 

고객을 위해 편안한 휴게실도

있더라고요~

 

음료수, 과자, 커피, TV, 컴퓨터가

준비되어 있어요

 

컴퓨터로 바로 달려가는

예랑이...

흥5

 

 

믿고사는 우수상품 입점매장 이라는

플랜카드가 똭!

 

매장이 정말 넓었어요

이 넓은 매장이 2층도 있더라구용

 

2층엔 아직 올라가보지 못했지만

예물 찾으러 갈땐 올라가 보지 않을까...요..?

 

 

내부를 구경하다 보니

저희를 상담해 주실 이사님이 오셨어요

 

어떤 디자인을 좋아하냐고 물어보셨는데

딱히.. 잘... 모르겠다고 했어요 ㅋㅋㅋ

 

저희 커플링을 보시더니

여러 제품을 보여주시고 끼워주시고

설명해주시고~

 

여러개 끼워보고 나서 이사님이

저는 화려한걸 좋아하고

예랑이는 심플한걸 좋아하는 거 같다고..

 

제가 고른 디자인 중에 예랑이가

선택해야 될것 같다고 하셨어요ㅋㅋ

 

 

커플링만 30개 이상은 껴봤던거 같아요..

땀까지 흘리며 이제품 저제품 보여주신

이사님 수고 많으셨어요

뿌잉3

 

 

결혼반지는 평생끼는 반지여서

처음 눈에 들어오는 화려한 것보다는

오래껴도 질리지 않는

심플한 디자인이 좋은거라는 말씀듣고 겨울 결정했네요

 

디자인 유출을 방지하기 위해

반지는 모자이크...ㅋㅋ

 

 

 

결혼반지를 고른뒤에

제 다이아 반지 고르기를

시작했어요 ㅋㅋ

 

결제 금액에 따라

다이아몬드를 2부,3부,5부를 제공해주는데

저는 여기서 받은

다이아 몬드로 밴드만 구매해서

다이아 몬드 반지도 했네요 ㅋㅋ

 

다이아몬드 반지도 정말

다양하고 이쁘더라구용

하트3

 

고민된건.. 지금 제 나이때 끼면 이쁜 반지랑

30대 후반 이후로 끼면 이쁜 반지랑

다르다는 점때문에

디자인을 고르기가 참... 힘들었는데

 

그런 제 모습을 보시던 이사님이

지금 이쁜 반지로 하고

10년 이후에 다른 반지에

다이아 몬드를 옮기는 방법도 있다고~^^

 

그말을 듣고 바로 결정했네요 ㅋㅋㅋ

 

다이아 몬드 반지도

디자인 유출을 방지하기 위해

모자이크 처리~^^!!

 

가격도 많이 할인해 주시고

사은품도 이것저것 많이 챙겨주시고

특히 다이아몬드 세트를 하지 않고

반지만 했는데 반지에 어울리는

주얼리 세트도 사은품으로 주셔서 좋앗어용ㅋㅋ

 

어머니 코사지도 주시고^^

 

아래는 사은품으로 받은 세트에요

 

이것도 디자인 유출 방지를 위해

모자이크 ㅋㅋ

 

 

디자인도 정말 고급스러운 것도 많고

독특한 디자인도 많고

한 디자인을 여러개 판매하지 않는다고 해서 그런지

보지 못했던 디자인들이 많긴 하더라고용ㅋㅋㅋ

 

이렇게 열심히 고르고 나니

1시간40분이 흘려가 있었어요

 

제가 고민을 많이 하긴 했나봐요;;ㅋㅋ

 

 

강남에 위치해 있어서

박람회때 가계약을 하고 나서도

많이 비쌀까봐 걱정이 되...

그냥 종로로 가서 할까 고민도 많이 했었는데

 

금액도 종로랑 차이 안나게 한것 같네요~

 

아! 제가 생각하기에

오르시아의 제일 큰 장점은

평생 AS가 된다는거에요~!!

 

스크래치는 물론이고

골드도 화이트골드, 엘로우골드, 핑크골드를

원하는대로 왔다갔다 할수 있데요~

 

질린다 싶으면 색상 바꿔서 끼는게 특별해서

정말 좋네요

그냥 종로로 갔으면 후회했을 거에요>.<

 

예물 찾으러 갈때

티아라 대여 해주는데

그것도 너무 기대되요~

꺅

 

예물 맞추고 지인 소개를 하면

박람회에서 계약하지 않아도

제가 받은 혜택 그대로 받을 수 있다고하니

혹시 예물 하셔야하면 댓글 남겨주세요~

 

 

 

 

'♡Wedding♥' 카테고리의 다른 글

[D-168] 허니문 예약(발리)  (0) 2014.08.09
[D-157] 상견례  (0) 2014.07.07

1.   CodeDom Lambda 비교

 

 

CodeDom

Lambda

변수 선언

가능                                      

불가 (단 하나의 표현식만 가능)

함수 작성

사용자가 C# 문법을 알아야함

간단하게 식 사용

Math 및 기타

라이브러리 지원

지원

지원(lambda-parser 오픈소스 사용)

컴파일 오류

오류 위치 확인 가능

오류 위치 확인 어려움

컴파일 형태

소스코드->CodeDom 그래프->IL 컴파일 (개발 복잡)

1.     Dll 파일 형태

2.     메모리 형태

소스코드->Expression tree->IL 컴파일

(소스코드 관리 편함)

1.     메모리 형태

호출 속도

1.     Func Delegate로 컴파일시 빠름, 단 함수 형태가 정의 되어있어야함

2.     DynamicInvoke는 느리지만 유연함

 

 

 

 

 

 

 

1.1 변수 선언

Lambda는 단 하나의 표현식만 가능하다. 모든 클래스나 메소드, 또는 선언문은 위해 설계되지 않아서 변수 사용은 불가능하다.

 

- CodeDom

 

-Lambda

 

 

 

 

1.2 Math 및 기타 라이브러리 사용

-CodeDom

 

 

-Lambda

 

 

 

1.3 컴파일 오류

-CodeDom

 

-Lambda

 

1.4 컴파일

CodeDOM CodeDOM 그래프, Lambda는 익스프레션 트리 형태로 변환되어 컴파일 된다. 익스프레션 트리는 CodeDOM과 크게 다를 바가 없지만, 두가지 차이가 있다.

첫째, 익스프레션 트리는 단 하나의 표현식만 가능하다. 모든 클래스나 메소드, 또는 선언문은 위해 설계되지 않았다.

둘째, C#은 언어에서 람다 식과 마찬가지로 직접적으로 익스프레션 트리를 지원한다.

 

-CodeDom

Windows에서는 개별 어셈블리 언로드를 지원하지 않는다. 대신 프로그램 도메인을 언로드하면 어셈블리도 같이 언로드가 된다. 하나의 프로세스에서는 주 프로그램 도메인(1)과 보조 프로그램 도메인(N)을 만들 수 있다. 보조 프로그램 도메인을 하나 생성하여 그 도메인에 어셈블리를 로드하여 사용하고, 재 컴파일시 도메인을 언로드하고 다시 로드하는 방식으로 수행하면 프로그램을 재시작하지 않고 사용자 정의 함수를 호출 할 수 있다.

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CalcDynamicCompile {     class AssemblyHelper :IDisposable     {         AppDomain newAppDomain;         AssemblyLoader proxy;                  internal void LoadAssembly(string assemName)         {             AppDomainSetup setup = new AppDomainSetup();             setup.ShadowCopyFiles = "true";             newAppDomain = AppDomain.CreateDomain("newDomain"null, setup);             proxy = newAppDomain.CreateInstanceAndUnwrap(typeof(AssemblyLoader).Assembly.FullName, 

typeof(AssemblyLoader).FullName) as AssemblyLoader;             proxy.LoadAssembly(assemName);         }         internal string LoadCode()         {             return proxy.LoadCode();         }                  internal void CreateInstance()         {             this.proxy.CreateInstance();                      }         internal void CreateDelegate(string methodName)         {             this.proxy.CreateDelegate(methodName);         }

        void IDisposable.Dispose()         {             proxy = null;             AppDomain.Unload(newAppDomain);             newAppDomain = null;         }         internal void Test(object[] param)         {             this.proxy.Test(param);         }     } }

 

 문제점은 도메인간에는 데이터가 공유되지 않기 때문에, MarshalByRefObject(응용 프로그램 도메인 간 경계를 넘어 개체에 엑세스할 수 있는 Abstract Class) Class를 상속 받은 개체에서만 사용자 정의 함수를 호출 할 수 있다. AppDomain으로 메소드 호출시에 Type이나 Assembly 등의 개체가 전달되거나 반환되면 상대방 AppDomain 측에서 해당 어셈블리의 로드가 자동으로 일어난다. 따라서 어셈블리의 동적 로드와 언로드의 목적 달성을 위해서는 이런 종류의 호출은 피해야 한다.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; using System.Diagnostics; namespace CalcDynamicCompile {     public class AssemblyLoader : MarshalByRefObject     {         Assembly assem;         object instance;

Delegate dele;         Func<floatfloatfloat> func;         public void LoadAssembly(string filename)         {             assem = Assembly.LoadFile(filename);         }         public override object InitializeLifetimeService()         {             // 이 객체가 원격 도메인 유휴 시간에 의해 자동으로 삭제되지 않게 함             return null;         }         internal string LoadCode()         {             string code = string.Empty;             string[] list = assem.GetManifestResourceNames();             if (list.Length > 0)             {                 using (System.Resources.ResourceReader sr = new System.Resources.ResourceReader(assem.GetManifestResourceStream(list[0])))                 {                     string resourceType;                     byte[] resourceData;                     sr.GetResourceData("code.txt"out resourceType, out resourceData);                     code = Encoding.ASCII.GetString(resourceData).Remove(0, 4);                 }             }             return code;         }         internal void CreateInstance()         {             Type type = assem.GetExportedTypes()[0];             instance = Activator.CreateInstance(type);         }         internal void CreateDelegate(string methodName)         {             Type type = assem.GetExportedTypes()[0];             MethodInfo info = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); ;             List<Type> tArgs = new List<Type>();             foreach (var param in info.GetParameters())                 tArgs.Add(param.ParameterType);             tArgs.Add(info.ReturnType);             Type delDecltype = System.Linq.Expressions.Expression.GetDelegateType(tArgs.ToArray());             this.dele = Delegate.CreateDelegate(delDecltype, this.instance, info);             this.func = (Func<floatfloatfloat>)this.dele;         }         internal void Test(object[] param)         {             Stopwatch sw = Stopwatch.StartNew();             float res = 0;             for (int i = 0; i < 100000; i++)             {                 if (param == null)                 {                     res = (float)this.dele.DynamicInvoke(null);                 }                 else                 {                     res = (float)this.dele.DynamicInvoke(param);                 }             }             sw.Stop();             Console.WriteLine(string.Format("DynamicInvoke : {0}", sw.Elapsed.ToString()), res.ToString());             sw = Stopwatch.StartNew();             for (int i = 0; i < 100000; i++)             {                 res = this.func((float)param[0], (float)param[1]);             }             sw.Stop();             Console.WriteLine(string.Format("FuncInvoke : {0}", sw.Elapsed.ToString()), res.ToString());             sw = Stopwatch.StartNew();             for (int i = 0; i < 100000; i++)             {                 res = ((float)param[0] * (float)param[1]) / 2 + 3 - 2 * 321;             }             sw.Stop();             Console.WriteLine(string.Format("Call : {0}\n", sw.Elapsed.ToString()), res.ToString());         }         float Test(float a, float b)         {             return (a * b) / 2 + 3 - 2 * 321;         }     }

 

 Code 저장 : 사용자가 작성한 Code를 저장하기 위해선 다른 Text파일로 저장 및 관리 해두는 방법과 Dll 파일의 EmbeddedResource 기능을 이용하는 방법이 있다.

컴파일시 ResourceWriter 개체를 이용해 Resource를 만들어서 사용자가 작성한 코드를 Resource 파일로 작성 후 Recource 파일을 어셈블리에 추가시키면 된다.

System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.IncludeDebugInformation = false;
parameters.GenerateInMemory = true;
 
System.Resources.ResourceWriter writer = new System.Resources.ResourceWriter("Resources.resx");
writer.AddResource("code.txt"Encoding.ASCII.GetBytes(code));
writer.Generate();
writer.Close();
parameters.EmbeddedResources.Add("Resources.resx");
 
 
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
parameters.ReferencedAssemblies.Add("System.Data.dll");
parameters.ReferencedAssemblies.Add("System.Drawing.dll");
parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
 
parameters.OutputAssembly = DllName;
 
CompilerResults r = CodeDomProvider.CreateProvider("CSharp").CompileAssemblyFromSource(parameters, code);
if (r.Errors.HasErrors == true)
{
    CompilerError err = r.Errors[0];
    MessageBox.Show(string.Format("Line:{0}, Column:{1}, ErrorNumber{2}\r\nMessage:{3}"
       err.Line.ToString(), err.Column.ToString(), err.ErrorNumber.ToString(), err.ErrorText));
}

로드시에는 역으로 어셈블리에서 Resource를 검색 후 ResourceReader 개체를 이용해 Resource를 읽는다.

string code = string.Empty;
 
if (File.Exists(DllName))
{
    using (AssemblyHelper assem = new AssemblyHelper())
    {
        assem.LoadAssembly(Application.StartupPath + "\\" + DllName);
        code = assem.LoadCode();
    }
}
 
return code;

 

-Lambda

코드 형태의 문자열을 Lambda식으로 변경하는 기능은 .Net에서 제공해주지 않아서 직접구현하거나 오픈 소스를 이용해야한다. http://code.google.com/p/lambda-parser/ 오픈소스를 이용하면 응용 프로그램에 로드된 라이브러리는 모두 사용 할 수 있다. Parse 메서드는 String 형태의 Code와 파라미터의 타입 정보, 사용할 클래스의 NameSpace를 넘겨주면 Expression을 생성한다. 그 이후 Compile 메서드를 통해 Delegate를 생성한다.

 

string code = this.tbCode.Text.Trim().Split('=')[1];
if (string.IsNullOrEmpty(code))
    return;
code = this.tbCode.Text;
 
 
LambdaExpression ex = ExpressionParser.Parse(code, nullthis.parameters.ToArray(), 
           "System""System.Collections.Generic");
 
this.dele = ex.Compile();
 
this.func = (Func<floatfloatfloat>)dele;
 
MessageBox.Show("Success");

 

 

 

1.5 CodeDom, Lambda 테스트

테스트 결과

  컴파일 모드 : Release

테스트한 식 : (a * b) / 2 + 3 - 2 * 321

테스트 값 : float a = 2, float b = 3

호출 테스트 수 : 100,000

총 테스트 수: 6

 

CodeDom, Lambda 테스트 코드

Stopwatch sw = Stopwatch.StartNew();
 
float res = 0;
 
for (int i = 0; i < 100000; i++)
{
    if (param == null)
    {
        res = (float)this.dele.DynamicInvoke(null);
    }
    else
    {
        res = (float)this.dele.DynamicInvoke(param);
    }
}
sw.Stop();
 
Console.WriteLine(string.Format("DynamicInvoke : {0}", sw.Elapsed.ToString()), res.ToString());
 
 
sw = Stopwatch.StartNew();
 
for (int i = 0; i < 100000; i++)
{
    res = this.func((float)param[0], (float)param[1]);
}
 
sw.Stop();
 
Console.WriteLine(string.Format("FuncInvoke : {0}", sw.Elapsed.ToString()), res.ToString());
 
sw = Stopwatch.StartNew();
 
for (int i = 0; i < 100000; i++)
{
    res = ((float)param[0] * (float)param[1]) / 2 + 3 - 2 * 321;
}
 
sw.Stop();
 
Console.WriteLine(string.Format("Call : {0}\n", sw.Elapsed.ToString()), res.ToString());

 

 

CodeDom 결과 :

Dynamic

Func

CSharp

테스트1

0.0648687

0.0008836

0.0004886

테스트2

0.0615519

0.0008796

0.0004813

테스트3

0.0621032

0.0008879

0.0004833

테스트4

0.0618416

0.0008455

0.0004631

테스트5

0.0614814

0.0008925

0.0004909

테스트6

0.0619039

0.0008714

0.0004929

평균

0.062291783

0.00087675

0.00048335

Call 기준(배수)

128.8751078

1.813902969

1

1 CodeDom 테스트 결과

 

Lambda 결과 :

Dynamic

Func

CSharp

테스트1

0.0962379

0.0009402

0.0004741

테스트2

0.0890706

0.000969

0.0005181

테스트3

0.07660805

0.0009647

0.0005141

테스트4

0.065423

0.0010326

0.0004853

테스트5

0.0898079

0.0009634

0.0004621

테스트6

0.0904247

0.00097

0.000487

평균

0.084595358

0.000973317

0.000490117

CSharp 기준(배수)

172.6024926

1.985887714

1

2 Lambda 테스트 결과

1.6  결론

지금까지 CodeDom Lambda를 테스트 해보았다. 속도 테스트 결과 CodeDom이 약간 우세하였다. 내가 생각하는 장단점은 아래와 같다. 둘 중 하나를 선택하라면 Lambda식이 적합한 것 같다.

 

CodeDom의 장점은 변수의 선언 및 복잡한 식의 계산을 쉽게 할 수 있다는 것이다. 단점은 사용자가 C# 언어를 학습 해야 하고, 함수의 네이밍, 메모리 관리 등 개발이 복잡하다는 것이다.

Lambda의 장점은 간편한 식을 작성 할 수 있고, 사용자에게 친숙하고, 함수의 관리가 편하다. 단점은 변수의 선언 및 복잡한 식은 설정하기 어렵다.

 

프로젝트 : CalcDynamicCompile.zip 

 

 

1.   Math Expression Parser 비교

 

1.1 DataTable

.Net에서 제공하는 DataTable Class Compute 메서드를 이용해 식을 계산한 코드이다. 먼저 a, b 문자를 값으로 치환한 후 계산을 진행한다. Compute 메서드의 반환값은 object로써 type에 맞게 캐스팅 해주어야하는 단점이 있다. 테스트는 아래와 같이 진행하였다.

object res = null;
DataTable dt = new DataTable();
 
 
string exp = expression;
foreach (KeyValuePair<stringstring> item in values)
{
    exp = exp.Replace(item.Key, item.Value);
}
 
Stopwatch st = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
    res = dt.Compute(exp, null);
    Type type = res.GetType();
 
    if (type == typeof(int))
    {
        int a = (int)res;
    }
    else
    {
        double b = (double)res;
    }
}
st.Stop();
Console.WriteLine(string.Format("DataTable = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

1.2 Ncalc

CodePlex에 등록되어 있는 오픈소스로써 System.Math 클래스의 메서들과 사용자 정의 함수를 지원한다. 사용자 정의 함수는 이벤트 방식으로 함수명으로 비교해서 개발자가 직접 처리를 해주어야 한다.

Debug.Assert(0 == new Expression("Sin(0)").Evaluate());

  Debug.Assert(2 == new Expression("Sqrt(4)").Evaluate());

Debug.Assert(0 == new Expression("Tan(0)").Evaluate());

 

//함수 처리

Expression e = new Expression("SecretOperation(3, 6)");

  e.EvaluateFunction += delegate(string name, FunctionArgs args)

      {

          if (name == "SecretOperation")

              args.Result= (int)args.Parameters[0].Evaluate() + (int)args.Parameters[1].Evaluate();

      };

  Debug.Assert(9 == e.Evaluate());

 

테스트는 아래와 같이 진행하였다.

object res = null;
NCalc.Expression ex = new NCalc.Expression(expression);
 
ex.Parameters.Clear();
 
Dictionary<stringobject> v = new Dictionary<stringobject>();
 
foreach (KeyValuePair<stringstring> item in values)
{
    ex.Parameters.Add(item.Key, Convert.ToSingle(item.Value));
}
 
Stopwatch st = Stopwatch.StartNew();
 
 
for (int i = 0; i < 100000; i++)
{
    res = ex.Evaluate();
}
 
st.Stop();
Console.WriteLine(string.Format("NCalc = {0} : {1}", st.Elapsed.ToString(), res.ToString())); 

 

1.3 Flee

CodePlex에 등록되어 있는 오픈 소스로써 Fast Lightweight Expression Evaluator라는 이름과 같이 테스트한 오픈소스 중에서는 가장 빠르다. System.Math Class 및 타 Class를 등록해서 사용 할 수있고, 사용자 정의 함수 기능을 제공한다. 사용자 정의 함수는 문자열로 정의 할 수 있지만, 매개변수가 바뀔시 Recalculate라는 메서드를 호출하여 엔진 내부를 수정 해야 하는 문제가 있다.

 

// 함수 테스트
CalculationEngine engine = new CalculationEngine();
ExpressionContext context = new ExpressionContext();
 
 
context.Variables.Add("a", 2);
context.Variables.Add("b", 2);
 
engine.Add("Func1""(a*b) + 2.0", context);
 
 
Stopwatch st = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 800; i++)
{
    res = engine.GetResult<double>("Func1");
    context.Variables["a"] = 3;
    engine.Recalculate("Func1");
}
st.Stop();
Console.WriteLine(string.Format("FleeFunc = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

테스트는 아래와 같이 진행하였다.

ExpressionContext context = new ExpressionContext();
 
double res = double.NaN;
 
context.Variables.Clear();
            
foreach (KeyValuePair<stringstring> item in values)
{
    context.Variables[item.Key] = Convert.ToDouble(item.Value);
}
 
IGenericExpression<double> exp = context.CompileGeneric<double>(expression);
 
Stopwatch st = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
    res = exp.Evaluate();
}
st.Stop();
Console.WriteLine(string.Format("Flee = {0} : {1}", st.Elapsed.ToString(), res.ToString()));

 

1.4 MathParseNet

CodeProject에 등록되어 있는 오픈 소스로써 sin, cos, tg, ctg 등 기본적인 수학 함수를 제공한다. 식의 해석과 동시에 값을 반환하는 형식이여서 오픈 소스 중에 가장 느렸고, 반환 값의 타입은 int, double 두개의 타입만 존재한다.

MathParserNet.Parser parser = new MathParserNet.Parser();
 
double res = double.NaN;
parser.RemoveAllVariables();
 
foreach (KeyValuePair<stringstring> item in values)
{
    parser.AddVariable(item.Key, item.Value);
}
 
Stopwatch st = Stopwatch.StartNew();
 
for (int i = 0; i < 100000; i++)
{
    MathParserNet.SimplificationReturnValue ret = parser.Simplify(expression);
    if (ret.ReturnType == MathParserNet.SimplificationReturnValue.ReturnTypes.Integer)
    {
        res = ret.IntValue;
    }
    else
    {
        res = ret.DoubleValue;
    }
}
st.Stop();
Console.WriteLine(string.Format("MathParseNet = {0} : {1}", st.Elapsed.ToString(),res.ToString()));

 

 

 

1.5  테스트

  컴파일 모드 : Release

테스트한 식 : (a * b) / 2 + 3 - 2 * 321

테스트 값 : float a = 2, float b = 3

호출 테스트 수 : 100,000

 

테스트 결과:

CSharp

Lambda

DataTable

Ncalc

Flee

MathParseNet

Test1

0.000352

0.000498

0.433453

0.205334

0.017759

14.45983

Test2

0.000259

0.0005

0.350152

0.204596

0.017735

14.61664

Test3

0.00028

0.000492

0.34059

0.154331

0.017455

14.54161

Test4

0.000243

0.000489

0.339338

0.154261

0.017464

14.52951

Test5

0.000251

0.000552

0.3525

0.206181

0.018056

14.5986

평균

0.000277

0.000506

0.363207

0.184941

0.017694

14.54924

CSharp 기준(배수)

1

1.827653

1311.215

667.656

63.87588

52524.33

3 Parser 테스트 결과

 

1.6 결론

Flee 오픈소스가 가장 빠르지만, CSharp으로 하드코딩한 연산에 비해 63배나 느렸다. Parser들은 속도에 민간한 프로젝트에 적용하기는 힘들 것 같다.

 

 

프로젝트 :AboutCalculParser.zip

 

 

+ Recent posts