이 블로그 검색

2023년 2월 25일 토요일

byte_rb : rust 에서 구현된 ring buffer

rust 에서 고정길이 메모리 할당 후 memcpy 로 구현한 ring buffer 

https://github.com/jeremyko/byte_rb

https://crates.io/crates/byte_rb

https://docs.rs/byte_rb/1.0.0/byte_rb/


2022년 9월 12일 월요일

https://jeremyko.github.io/ 를 만들었다

https://jeremyko.github.io/

그 동안 코드 편집 하는 게 너무 번거로웠는데 markdown 이 지원되는 github pages 가  좋은거 같다 

2022년 9월 2일 금요일

(python) docker container 에서 scipy, numpy 사용 시 thread 과다 생성 문제 (incorrect cpu count)

개발 중인 python 프로젝트에서 scipy 패키지 interpolate 를 사용하는 코드가 있는데, docker 기반 클라우드 환경에서 실행하니 먹통이 되고 멈추는 현상이 발생 했다. 하지만, 이 코드를 내 랩탑 에서 돌려보면, 정상 동작한다.

문제의 원인을 찾아보니, docker container 를 생성하면서 할당한 cpu 개수와 실제 머신의 전체 CPU 개수 불일치로 인한 문제였다. 이 현상에 대해 정리 해 본다.


  • docker container 기반에서 OpenBLAS, MLK 를 사용하는 numpy, scipy 등의 패키지 내부에서 과도한 thread 생성이 안되게 주의 해야 한다.
  • 비록 명시적으로 thread 를 사용하지 않았어도, numpy, scipy 내부적으로는 multi thread 가 생성 된다는 것을 알아둘 필요가 있다.
  • 코드가 동작하는 환경을 분석하고, 성능 문제가 있는 경우에만 시도한다


좀 더 자세히 알아보면, 

2022년 8월 21일 일요일

(pthon) pandas 처리 속도 개선에 대하여

지금 하고 있는 프로젝트에서 python pandas 와 numpy를 사용해서 데이터를 처리하는 부분이 있다.
그런데 기존에 있던 처리 속도가 느려서 이 부분을 검토하면서,
처리 속도를 높이기 위해 이것 저것 수정해서 테스트 하다 보니 알게 된 것들이 있어서 정리해 본다.


- 최선의 방식은 numpy ndarray vectorization 처리다.

- for loop를 이용해서 모든 데이터를 순회하는 방식은 피해야 한다. 
  (nested for loop 방식은 어떤 식 으로 든 개선의 여지가 있다)


그럼 위 내용에 대해서 상세히 확인 해 보도록 하자.
우선 기존 소스 분석을 통해서 로직을 심플 하게 추려서 만들어 보면 다음과 같았다.

2022년 3월 24일 목요일

golang 1.18의 workspace mode 알아보기

이번에 1.18 버전이 나오면서 크게 변경된 것 (generic, fuzzing, 성능 향상, workspace 모드) 중에서 나에겐 workspace 의 유용함이 가장 먼저 다가왔다. 

실제 프로젝트에서 golang 으로 개발하는 경우에 아주 유용한 기능이라고 생각된다. 

workspace 는 개발자가 동시에 여러 모듈들을 생성/수정 하면서 개발하는 경우 유용하게 사용될 기능이다.

예를 들자면, 어떤 모듈A 를 수정해야 하는데 , A모듈이 사용 중인 모듈B 도 같이 동시에 수정이 필요한 경우를 가정해보자.

개발 시 분명히 마주치게 될 이런 문제를 1.18 버전 이전에는 어떻게 해결했냐 하면, 

A모듈의 go.mod 파일에서 replace 지시자를 사용해서, B모듈의 경로를, 지금 수정하는 로컬 위치로 변경 해줘야만 했다. 

(이전글 참조 : golang module 작성, 타 모듈에서 로컬 테스트 및 배포 개념 정리)

로컬 경로는 개발자마다 전부 다를 것이므로, 소스 관리 차원에서도 함부로 replace 지시자 가 들어간 go.mod 파일을 소스 repo 에 commit,push 할 수 없었다. 한마디로 매우 성가시고 불편했다.

만약 replace 사용 없이 하려면 각각의 모듈 별로 개별 test 코드를 만들어서 독립적으로 완벽히 테스트 하면서 개발 후, 동시에 repo에 발행한다며, 아마도 어쩌면? 가능 했을지도 모른다. 

하지만 개발자는 신이 아니기에, 이런 식으로 개발 할 수는 없을 듯 하다. A 를 수정하다 보면 B 도 수정 필요하고 또 그 반대의 경우도 수시로 발생 될 수 있기 때문이다.

그런데 이제 workspace 를 사용하면 훨씬 편한 개발이 가능해졌다. go.work 파일이 존재하면 workspace mode로 동작하게 된다. 

그럼 이전 글에서 설명된 예제를 workspace 를 사용하는 것으로 수정을 해본다.

 

2022년 1월 2일 일요일

GOSOF : A simple yet quite practical socket framework made with golang.

 

https://github.com/jeremyko/gosof


Instead of the simple socket echo example that comes up a lot if you search, I tried to implement it so that it can properly handle the buffering of tcp data that can be split into pieces or transmitted all at once. And to increase reusability, I implemented it so that it can be used like a framework.

  • The framework calls the user-specified callback.
  • For TCP, the total size of user data is passed to the framework via a callback, and the framework does TCP buffering automatically.
  • Byte data is exchanged.
  • Supports TCP, UDP and Domain Socket.


When sending a byte message composed of a fixed-length header and variable-length body data, it may be useful as it can reduce the work a little.

udp and domain socket are also supported, but this is not much different from using the existing net package as it is, so there is no special point.

 

golang 으로 만든 간단하면서도 꽤 실용적인 socket 프레임워크.

검색하면 많이 나오는 단순한 socket echo 예제 대신, 조각으로 쪼개지거나, 한번에 다 전송될수 있는 tcp 의 데이터 버퍼링 처리를 제대로 처리 할 수 있게 끔 구현해 봤다. 그리고 재활용성을 높이기 위해 프레임워크 처럼 사용할수 있게 구현 해 봤다. 몇가지 특징을 나열하면,

  • 프레임워크가 사용자 지정 콜백을 호출한다.
  • TCP의 경우 사용자 데이터의 전체 크기는 콜백을 통해 프레임워크에 전달되고 프레임워크는 TCP 버퍼링을 자동으로 수행 해준다.
  • 바이트 데이터를 주고 받는다
  • TCP, UDP 및 도메인 소켓을 지원


고정길이 헤더와 가변길이 body 데이터로 구성된 byte 메시지를 전송할때 조금이나마 작업을 줄일수 있어서, 나름 유용할거 같다.

udp 나 domain socket 도 지원하지만, 이건 뭐 기존 net package 를 그대로 사용하는것과 거의 차이가 없기 때문에 별다른 점은 없겠다. 

https://github.com/jeremyko/ASockLib 과 비슷한 사용법을 가지고 있다.



2021년 11월 22일 월요일

mariadb maxscale 사용 시 주의점 (readwritesplit)

이번에 프로젝트를 하면서 겪었던 상황을 정리해본다.

mariadb MaxScale 은 db proxy 로 위치투명성, 고가용성, 로드밸런싱 등의 목적으로 사용된다. 그런데 혹시 코드중에서 insert 후 바로 select 를 수행하는 경우에는, 방금 저장한 내용을 못 가져 오는 경우가 발생할수 있다. 

readwritesplit 라는 모듈의 동작으로 발생될수 있는 상황인데, maxscale 은 위에 언급된 여러 기능을 구현하기 위해서 동적으로 로드되는(즉 shared library) 여러개의 모듈들이 존재한다. router 는 이러한 모듈의 한 종류이며, router 유형의 모듈 중에서, 읽기 성능 향상을 위한 모듈이 바로 readwritesplit 이다. 

글자 그대로, 이것은 사용자의 query 가 읽기인지 쓰기 인지에 따라 master 혹은 slave 에서 분리 처리되게 해준다. 즉 읽기 query 는 여러개의 slave 중 하나에서 처리되고, 쓰기 query 는 master(single node)에서만 처리된다.

그런데, 이로 인해 문제가 되는 상황은, insert 후 바로 동일 데이터를 select 하는 경우에, 방금 저장한 데이터가 완전하게 slave 로 복제가 안된 상황이 발생될수 있고, 이렇게 되면 조회 결과가 없는 것처럼 처리될수 있다.

그래서 문서를 통해 찾은 해결책은 다음 2 가지가 있다.

  • mariadb 와 maxscale 설정을 변경하거나 아니면 
  • 사용자의 프로그램에서 동일한 트랜잭션으로 묶는다. 문서를 보면, 동일한 트랜잭션 안에서는 select 쿼리가 무조건 master로 라우팅되므로 일관성 문제가 해결 된다.

 

참고

https://mariadb.com/kb/en/mariadb-maxscale-6-readwritesplit/

https://mariadb.com/kb/en/mariadb-maxscale-6-readwritesplit/#limitations

https://mariadb.com/docs/solutions/maxscale/routers/readwritesplit/ensure-causal-consistency-maxscale-read-write-split-router/


2021년 8월 6일 금요일

golang : interface 로 전달받은 pointer 가 가르키는 type 을 찾기

reflect.Indirect 를 활용하면, interface 로 전달된 인자가 pointer인 경우, 그 pointer가 가르키는 실제 type 에 대한 정보를 알수 있다. 여러 type을 전달받는 공통 함수 등을 작성할때 유용한 tip

package main

import (
    "fmt"
    "reflect"
)

func testFunc(value interface{}) {
    fmt.Println("---------------------")
    fmt.Println("type = " + reflect.ValueOf(value).Type().String())
    fmt.Println("kind = " + reflect.ValueOf(value).Kind().String())
    if reflect.ValueOf(value).Kind()==reflect.Ptr {
	fmt.Println("--> pointer " )
	pointsToValue := reflect.Indirect( reflect.ValueOf(value))
	fmt.Println("-->",pointsToValue.Kind(), 
	    " - ",pointsToValue.Type(), " - ", pointsToValue)
	if pointsToValue.Kind()==reflect.Slice {
	    fmt.Println("--> slice !! " )
        }
    }
}

func main() {
    var testVar1 string
    var testVar2 []string
    var testVar3 []*string 
    
    testVar2 = append(testVar2,"A")
    testVar2 = append(testVar2,"B"
 
    testFunc(testVar1)
    testFunc(&testVar1)
    testFunc(testVar2)
    testFunc(&testVar2)
    testFunc(testVar3)
    testFunc(&testVar3)
}

 

https://play.golang.org/p/1PEOYIPdyFb


2021년 5월 29일 토요일

macbook pro 2012 mid LCD replacement (맥북 액정 교체기)

지금 사용중인 맥북 프로가 몇달전에 갑자기 화면에 세로줄들이 발생했다. 외부 디스플레이는 문제 없는 상태라서 로직 보드 문제는 아닌거 같다. 새로 살 필요까지는 없는거 같아서 맥북 수명 연장에 좀 투자 하기로 했다.

2021년 5월 1일 토요일

맥북 배터리 스로틀링

 

macbook pro 2012 mid 의 배터리를 교체하기 위해 제거하고, 지금 전원 어댑터만 연결해서 사용을 해보니 심각한 속도 저하가 발생하고 있다. 그냥 내 느낌인가 싶었는데 찾아보니,.. 정말로 맥북은 배터리가 없으면 cpu, gpu 쓰로틀링이 강제로 걸려서 체감 속도가 확 떨어진다고 한다. 전원 만으로는 감당 안되게 하드웨어 구조가 되있어서 부하가 걸리는 작업에는 배터리 + 전원이 같이 동작해야만 속도 저하가 안 일어 난다고 하니... 참 이게 뭔 말도 안되는 상황인지 모르겠다.. 애플이 배터리 장사할려고 이런식인지.. 윈도우 랩탑에서도 이런 문제가 있는지 모르겠지만 황당해서 남겨본다.

2021년 4월 27일 화요일

Go 1.16 에서 $GOPATH/src 에서 코드 작성하고 사용하기

Go 1.16 버전 부터는 기본적으로 module 을 사용하게 변경 되었다. 덕분에 GOPATH  와 상관없이 아무 위치에서든 자신의 소스파일을 작성하면 된다.  그리고 모듈을 사용하기 위한 go.mod 파일이 반드시 필요하게 되었다.  하지만 1.16 버전에서도 선택적으로 module 사용을 할지 말지 여부를 결정 할 수 있다. 예를 들어 기존 프로젝트 구조가 GOPATH 내 src 를 사용하는 경우등이 해당될수 있다.

2021년 4월 25일 일요일

go module과 package 관계, 그리고 module path 개념 정리

go 의 기본적인 개념 중에서 모듈, package 그리고 모듈 경로에 대해 알아본다. 처음에 개인적으로 많이 헷갈렸던 부분이라서 정리해 본다. 지금 우리가 go 로 어떤 프로젝트를 수행한다고 가정해 보면, 다음처럼 정리 할 수 있겠다. 

  • 이 프로젝트는 여러개의 모듈을 가질수 있다.
  • 각 모듈에는 여러개의 package들이 존재할수 있다.
  • 각 package 들은 1개 이상의 go 소스파일로 구성된다.
  • 모듈내의 각 package 들은 자신의 package 폴더를 go mod init 으로 지정한 모듈 경로 + 폴더로 만들면 된다. 
  • 패키지명은 (반드시) 경로의 마지막 문자열로 해준다.
  • 개발중인 모듈은 반드시 원격 저장소에 배포될 필요가 없다.
  • 로컬 개발환경에서 동시에 여러 모듈을 개발중이고, A모듈이 B모듈을 사용해야 한다면, B모듈의 경로를 개발 중인 로컬 경로로 변경하는 작업이 필요하다.(이건 예전 상황이고.. go 1.18 부터는 그냥 workspace 를 사용하면 됨)

위 내용들을 하나씩 살펴보자. (go 1.16 기준으로 작성됨)

2021년 4월 24일 토요일

go 에서 gRPC-Gateway 사용하기

이번에는 go 에서 gRPC-Gateway 를 사용하는 방법에 대해 알아보려 한다. 

최종 코드는 다음에서 확인 가능 : https://github.com/jeremyko/grpc-gateway-sample

앞서 살펴본 go 에서 proto buffer 사용하기 와 거의 비슷한 절차이나 gRPC-Gateway 사용을 위해 추가되는 절차가 있다. 다음 내용을 기초로 작성되었다 (그대로 따라 했더니 에러가 발생되어, 최신 go 버전에 맞게 내용이 추가된 부분이 있다. go 1.16 버전 기준).

https://grpc-ecosystem.github.io/grpc-gateway/docs/tutorials/introduction/

필요한 패키지 다운로드

go get google.golang.org/grpc
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get google.golang.org/protobuf/cmd/protoc-gen-go
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

2021년 4월 22일 목요일

go 에서 proto buffer 사용하기

1. proto buffer 를 정의
2. go 로 변환하여 모듈을 만들고
3. 이 모듈을 로컬에서 호출해서 사용 하는 간단한 예제를 정리해 본다 (go 1.16 버전을 기준)

최종 코드는 다음을 참고 : https://github.com/jeremyko/go-proto-buffer-sample

2021년 4월 15일 목요일

flutter : push-up mania

flutter 를 사용한 모바일 크로스 플랫폼 앱 개발 예제. 

https://play.google.com/store/apps/details?id=com.jeremyko.pui

뭘 일단 만들어볼까 하다가, 한 10년 전에 ios 앱으로 만들었던 푸쉬업 카운터를 또 만들어 봤음.

 


 

2021년 4월 3일 토요일

flutter : using mixed null safety for legacy packages

null safety 가 없는 기존 package 들을 최신 flutter, dart 개발 환경에서 사용하기.

flutter 프로젝트 내에서 dart 버전을 소스파일 단위로 다르게 지정하여 오래된 package 들도 null safety 에러가 안나게 개발할수 있다.  

2021년 3월 19일 금요일

golang module 작성, 타 모듈에서 로컬 테스트 및 배포 개념 정리

2022-03-24 update

go 1.18부터 도입된 workspace 기능을 사용하면 mod replace 를 대체 가능하다 

https://jeremyko.blogspot.com/2022/03/golang-118-workspace-mode.html

 

 

golang 모듈을 만들고 타 모듈에서 사용하는 것을 한번 정리해보았다.
내가 만들려고 하는 모듈이
github.com/jeremyko/my_mod 이며, 모듈 폴더는 ~/mydev/my_mod 라고 가정한다.