레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C#인 게시물을 표시합니다. 모든 게시물 표시

2022년 9월 7일 수요일

C# Async/Await Task 속도가 느릴 때 (TaskCompletionSource)

고전적인 개발 방법으로는 작업이 끝났는지 확인하기 위해서

작업 내용을 확인하는 루프를 만들어서 확인을 하는데


나는 이걸 mysql 풀링에 사용했었다.


그러니까 지금 사용 가능한 mysql 연결이 있는지를 task 에서

루프 돌면서 확인하는 방식으로 만들었던 것이다.


그런데 처음에 async/await task 방식이 문제라고 잘못 생각했던 것이

cpu 점유율을 너무 많이 먹었던 것이다.


ram이나 다른 리소스는 문제가 되지 않았다.

그저 cpu 점유율만 높았다. 그래서 이거 계속 써야 하나 싶었다.

그런데 써보니까 async 에서의 순차 실행이 참 편한 부분이 많았고

해결책을 찾아보니 내 코딩 스타일과 맞지 않았던 것이다.


루프 돌면서 쉬는 mysql 연결을 찾는 코드가 문제였는데

전체 확인하고나서 Task.Yield() 해서 한펌 쉬는 코드를 해놨는데

이게 유니티에서의 1프레임 단위가 아니었던 것이다.

결국 mysql 커넥션이 전부 사용중일때 많은 task 들이 yield를 하면서

루프를 도는데 이 텀이 너무 짧다보니 거의 무한루프(?) 돌듯이 계속 체크하면서

cpu를 다 먹었었다.


그래서 task 관련 공부를 더 했고 해결책을 찾았는데 그게

TaskCompletionSource였다.

값이 맞춰질때까지 대기하는 것이기 때문에 mysql을 다 쓴 후 반환하는 코드에서

mysql 연결 인덱스를 맞춰주니 yield를 사용할 필요가 없어서 cpu 사용율이

획기적으로 내려갔다.


사실 이건 내 코딩 스타일이 오래되서 그런거 같다. 하여간 문제는 해결이 되었고

이제 cpu 점유율 문제는 사라졌다.


2022년 4월 3일 일요일

C# CSV 파싱(여러줄 가능)

이전에는 데이터를 엑셀 데이터를 이용했는데 이건 좀 아닌거 같더라

그래서 CSV를 쓰려고 했는데 여러줄이 들어간 경우 때문에 안 쓰게 되었다.

이번에 현지화 관련 작업을 하면서 CSV를 쓰자고 생각이 들었고

CSV에서 어떤 방식으로 저장하는지를 연구해보았다. 일단 잘 동작한다. 

 
public static void ParsingCSV(string file_name,ref string[][] ret)
{
    ret = null;
    string all = ReadAllText(file_name);
    List<List<string>> lines = new List<List<string>>();
    List<string> ln = new List<string>();
    StringBuilder sb = new StringBuilder();
    bool is_string = false;
    int last = all.Length - 1;
    for(int i = 0; i < all.Length;++i)
    {
        Char c = all[i];
        if (is_string)
        {
            if (c == '"')
            {
                if (i < last && all[i + 1] == '"')
                { // " 2개가 연달아나오면 " 문자열을 써주면 된다.
                    sb.Append('"');
                    ++i;
                }
                else
                { // 문자열이 끝나는 상황
                    ln.Add(sb.ToString());
                    sb.Clear();
                    is_string = false;
                }
            }
            else sb.Append(c);
        }
        else
        {
            if (c == '"') is_string = true; // 문자열의 시작이다.
            else if (c == 0x0d)
            {
                ++i; // \r\n
                if (sb.Length > 0) ln.Add(sb.ToString());
                lines.Add(ln);
                sb.Clear();
                ln = new List<string>();
            }
            else if (c == ',')
            {
                if (sb.Length > 0)
                {
                    ln.Add(sb.ToString());
                    sb.Clear();
                }
                else ln.Add("");
            }
            else sb.Append(c);
        }
    }
    if (lines.Count <= 0) return;
    ret = new string[lines.Count][];
    for (int i = 0; i < ret.Length; ++i) ret[i] = lines[i].ToArray();
}
 "",",\r,\d, , 이 정도만 처리하면 되더라. 

 앞으로는 csv로 써보면서 문제 있으면 위 코드를 수정하게 될 것이다.

2022년 2월 27일 일요일

C# Litjson Extension

저는 C# 개발을 할때 json 라이브러리는 Litjson을 주로 사용합니다.


편하게 사용하기 위해서 정적 클래스 하나 만드러서 사용하다가 이번에는 익스텐션을 만들어 보았습니다.


확실히 편하게 사용할 수 있는 부분은 찾아보는 것이 좋은것 같습니다.


사용하는 litjson 라이브러는 0.17.0 버전입니다. 이전이나 이후도 별 상관은 없을것 같네요.

dotnet6로 만든 소스구요 null에 대한부분 ? 없애는 정도면 되지 않을까 싶네요.


사용법은

JsonData jd;

jd.GetInt();

jd.GetString();

아래 소스를 보시면 아시겠지만 어떻게든 값을 얻어옵니다.

타입 체크가 필요하면 하고 하면 될것이구요.

IsNumber의 경우 숫자 형태가 너무 많아서 추가했습니다.

필요한 것이 있으면 더 추가하면 될것이구요.

하여간 도움이 되면 좋겠습니다~


파일을 올릴수가 없네요.

소스입니다.

namespace LitJson
{
    internal static class LitjsonExtension
    {
        public static bool IsNumber(this JsonData jd)
        {
            switch (jd.GetJsonType())
            {
                case JsonType.Int:
                case JsonType.Long:
                case JsonType.Double: return true;
                default: return false;
            }
        }
        public static bool GetBool(this JsonData jd)
        {
            if (jd == null) return false;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToBoolean((string)jd);
                case JsonType.Int: return Convert.ToBoolean((int)jd);
                case JsonType.Long: return Convert.ToBoolean((long)jd);
                case JsonType.Double: return Convert.ToBoolean((double)jd);
                case JsonType.Boolean: return (bool)jd;
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return false;
            }
        }
        public static int GetInt(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToInt32((string)jd);
                case JsonType.Int: return (int)jd;
                case JsonType.Long: return Convert.ToInt32((long)jd);
                case JsonType.Double: return Convert.ToInt32((double)jd);
                case JsonType.Boolean: return Convert.ToInt32((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static long GetLong(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToInt64((string)jd);
                case JsonType.Int: return Convert.ToInt64((int)jd);
                case JsonType.Long: return (long)jd;
                case JsonType.Double: return Convert.ToInt64((double)jd);
                case JsonType.Boolean: return Convert.ToInt64((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static double GetDouble(this JsonData jd)
        {
            if (jd == null) return 0;
            switch (jd.GetJsonType())
            {
                case JsonType.String: return Convert.ToDouble((string)jd);
                case JsonType.Int: return Convert.ToDouble((int)jd);
                case JsonType.Long: return Convert.ToDouble((long)jd);
                case JsonType.Double: return (double)jd;
                case JsonType.Boolean: return Convert.ToDouble((bool)jd);
                case JsonType.None:
                case JsonType.Object:
                case JsonType.Array:
                default: return 0;
            }
        }
        public static string? GetString(this JsonData jd)
        {
            if (jd == null) return null;
            switch (jd.GetJsonType())
            {
                case JsonType.Object:
                case JsonType.Array: return jd.ToJson();
                case JsonType.String: return (string)jd;
                case JsonType.Int: return Convert.ToString((int)jd);
                case JsonType.Long: return Convert.ToString((long)jd);
                case JsonType.Double: return Convert.ToString((double)jd);
                case JsonType.Boolean: return Convert.ToString((bool)jd);
                case JsonType.None:
                default: return null;
            }
        }
    }
}

gtr9 pro, ai max+ 395, gpt-oss-120b 돌아간다~!

여러가지 샛팅을 해봤지만 잘 안되는 상황에서 검색을 해보니까 레모네이드 서버를 이용해서 amd에서 서빙하는것을 발견했다. 일단 윈도우에서 ram 64g vram 64g에서 돌아는 가는데 컨텍스트가 낮았다. 그런데 속도가 빠르고 gpu를 다 쓰길래 희망...