arcus-memcached icon indicating copy to clipboard operation
arcus-memcached copied to clipboard

Bspark/bulk bop insert

Open computerphilosopher opened this issue 6 years ago • 12 comments
trafficstars

@minkikim89

bop insert를 로깅하는 것이 가장 중요한 일 같아서 일단 커밋을 두 개로 나누었습니다. 첫 번째 커밋은 bop insert 시에만 로깅이 실행되도록 하였고 두 번째 커밋은 모든 콜렉션, 키밸류 관련 명령에서 실행되도록 고쳤습니다.

리뷰가 끝나면 rebase 하도록 하겠습니다.

변경 개요

cmd_in_second.c

cmd_in_second <command> <count>
ex) cmd_in_second bop insert 10000

사내 세미나에서 발표한 기능입니다.

  • 메모리 할당을 시작 부분에서만 받도록 해서 오버헤드를 줄였습니다.
  • 파일 출력을 별도 쓰레드로 분리시켰습니다.
  • write 시스템콜이 마지막 한번만 실행되도록 했습니다.
  • 시간을 매번 재지 않고 로그 500개를 묶어서 재도록 바꾸었습니다.
  • 별도 lock을 잡지 않고 STATS_LOCK()을 잡은 상태에서 실행되도록 했습니다.

stats.c

  • stats_prefix_record 함수의 인자로 client_ip를 넘기도록 바꾸었습니다.

computerphilosopher avatar Jul 31 '19 09:07 computerphilosopher

@minkikim89 code 기능의 정확성 위주로 먼저 review 해 주시고, coding style 등은 나중에 review 합시다.

jhpark816 avatar Jul 31 '19 12:07 jhpark816

@computerphilosopher stats_prefix 정보를 갱신하는 부분에서 logging하자고 하여 진행된 상태입니다. arcus-memcached 코드를 보면서 logging에 더 적합한 위치나 방법이 있던가요 ?

jhpark816 avatar Jul 31 '19 12:07 jhpark816

stats_prefix 외의 위치라면 process_command()에서 로깅 함수를 호출하는 것이 제일 적절하다고 생각합니다.

명령어를 파싱하는 함수에서 바로 로깅하는 것이기 때문에 흐름상 자연스럽고, 로깅에 필요한 명령어, client ip, key를 모두 인자로 받기 때문입니다.

stats_prefix 에서 로깅할 경우 파싱이 끝난 상태여서 잘못된 명령어가 기록될 가능성은 걱정하지 않아도 되는데 process_command() 로 위치를 바꿀 경우 별도의 예외 처리를 해야할 것 같습니다.

computerphilosopher avatar Jul 31 '19 13:07 computerphilosopher

@computerphilosopher 본 기능의 구현에 있어, 만족해야 할 사항이 있습니다.

  • stats_lock을 추가로 잡지 않는다. 즉, stats_lock을 잡게 되는 코드에 logging 기능 추가

위 요구 사항을 만족시키면서 적절한 위치와 방안이 있다면, 간단한 pseudo code로 나타내 주세요. stats_prefix_xxx() 내부에서 logging하는 방법과 비교해 보고자 합니다.

jhpark816 avatar Aug 01 '19 03:08 jhpark816

#memcached.c
def process_command():
    if cmd_in_second.state == on_logging:
    	STATS_LOCK()
	cmd_in_second.write(command, key, client_ip)
    	STATS_UNLOCK()
    
    if command == "get" or command == "bget":
    	process_get_command(command)
    ...
    elif command == "cmd_in_second" and cmd_in_second.state == not_started:
    	process_second_command(command)
    else:
    	print("ERROOR unkown command")
        return

def process_second_command(command):
    if bad_command_line_format(command):
        return False
    
    if already_started:
    	return False
        
    cmd_in_second.start()
    return True

#cmd_in_second.c
def start(command):
    if unknown_command(command):
    	return False
    
    buffer.init()
    timer.init()
    
    return True

def write(command, key, client_ip):
    if bad_command_line_format(command):
        return False
    
    if not command_to_log(command):
    	return False
    
    log = (command, key, client_ip)
    buffer.add(log)
    
    if buffer.full() and timer.diff(buffer) <= 1
    	buffer.flush()

    return True

computerphilosopher avatar Aug 01 '19 06:08 computerphilosopher

@computerphilosopher @minkikim89 코드를 확인해 보니, btree_elem_insert() 호출 직후가 가장 적합합니다.

  • 기존 stats 정보들도 모두 해당 engine 함수 호출 후에 갱신합니다.
  • logging 대상 요청인지 판별하여 logging 작업을 수행합니다.
  • stats_prefix_xxx() 함수 내부가 적당하긴 하나, 아래 이슈가 있습니다.
    • connection 구조체 포인터가 인자로 추가되어야 하고,
    • prefix stats을 다루는 곳에서 logging하는 것이 어색한 감이 있네요.
  • 따라서, stats_prefix_xxx() 수행 이후에
    • 조건 검사 후, command logging 함수를 호출하고,
    • command logging 내부에 별도 lock을 두어 사용해도 될 것 같습니다.

jhpark816 avatar Aug 01 '19 07:08 jhpark816

@minkikim89

리뷰 사항 반영해서 다시 푸쉬하였습니다.

computerphilosopher avatar Aug 02 '19 09:08 computerphilosopher

@minkikim89

STATS_LOCK 대신 별도 락을 가지는 버전을 푸쉬했습니다.

computerphilosopher avatar Aug 06 '19 05:08 computerphilosopher

@computerphilosopher PR에 이슈 링크를 추가해 주세요.

jhpark816 avatar Mar 17 '20 08:03 jhpark816

@jhpark816

관련 이슈가 아직 안 만들어졌습니다. 이 저장소에 새로 하나 만들까요?

computerphilosopher avatar Mar 17 '20 09:03 computerphilosopher

@computerphilosopher 이 내용에 관한 이슈는 arcus-works에 만들어 주세요.

jhpark816 avatar Mar 17 '20 09:03 jhpark816

https://github.com/jam2in/arcus-works/issues/158

computerphilosopher avatar Mar 17 '20 09:03 computerphilosopher