맨땅에 헤딩하는 사람

[Python] 수강신청, 티케팅, 서버 신호, 가장 정확한 시간에 신호보내기 본문

파이썬/이론

[Python] 수강신청, 티케팅, 서버 신호, 가장 정확한 시간에 신호보내기

purplechip 2020. 5. 9. 13:40

한정되어있는 재화를 판매할 때 사용하는 방법은 여러가지이다. 가격을 높여 수요를 억제하는 방법, 무작위에 의한 판매방법, 그리고 대부분의 판매자가 사용하는, 내가 생각하기에 가장 효율적이고 도덕적인 방법인 선착순 방식이 있다.

 

선착순 방식을 겪어보지 못한 사람은 없을 것이다. 좋아하는 스타의 콘서트, 수강신청, 주식 주문, 이번에 생긴 닌텐도 스위치 구입 등 선착순은 정말 어디에서든 존재하고 우리는 그 방식이 합리적이라 판단하며 그 방식을 따른다.

 

오프라인에서의 선착순 방식이란 오롯이 한 사람의 시간을 투자하는 개념이지만, 온라인에서의 선착순 방식은 인터넷이라는 효율적인 틀 안에서 얼마나 정확한 시간에 도착 신호를 보내는지의 싸움이 된다. 우리의 몸은 편해졌고 경쟁에 참여하기는 더 쉬워졌으나 이에 따른 경쟁력은 높아지게 되었다. 아래의 링크에서는 이를 파이썬 프로그램으로 해결하는 방법을 제시하고 있다.

https://medium.com/@whj2013123218/%EC%88%98%EA%B0%95-%EC%8B%A0%EC%B2%AD-%EB%B0%8F-%ED%8B%B0%EC%BC%80%ED%8C%85-%EC%84%B1%EA%B3%B5%EC%9D%84-%EC%9C%84%ED%95%9C-tip-%EB%B0%8F-python-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-facc9107abc7

 

수강 신청 및 티케팅 성공을 위한 Tip 및 Python 프로그램

1학년 때 선배들에게서 이런 말을 굉장히 많이 들었다.

medium.com

윗 글을 읽으며 디테일하다고 느꼈다. request 모듈 요청시간을 고려하여 대신 datetime 모듈을 사용한 점, 서버에 요청보내는 시간과 요청량 폭증으로 인한 지연 시간을 두는 점 등을 고려하여 0.4초 전에 요청을 보내야 한다 주장하는 점 등이 그것이다. 윗 글에서는 다음과 같은 코드를 제공한다.

endhope=False
while not endhope:
    tim=dt.datetime.now()
    if tim.second>=59 and tim.microsecond>600000:
        pyautogui.click(1301,722)
        endhope=True
        print(tim)
    else:
        time.sleep(0.1)
        print(tim)

 

여기서 나는 시간을 비교하는 연산의 속도가 궁금해졌다. 즉, datetime 객체를 비교하는 것과 위 코드에서처럼 클래스의 어트리뷰트를 비교하는 것 중 어떤 것이 속도가 빠를까? 빠를수록 서버요청 시간의 정확도가 향상될 것이다. 따라서 다음과 같이 case를 나눠 비교해보았다. (단순히 time.time()으로 해당 비교연산의 시간을 측정했을 때는 이상하게 모두 연산 시간이 걸리지 않는 것으로 나온다.)

 

  • case 1 : datetime 객체 끼리의 비교 / x [s] 000000 [us] / sleep 0.001
  • case 2 : datetime 객체 끼리의 비교 / x-1 [s] 999000 [us] / sleep 0.001
  • case 3 : 클래스 속성 비교 / x [s] 000000 [us] / sleep 0.001
  • case 4 : 클래스 속성 비교 / x-1 [s] 999000 [us] / sleep 0.001
  • case 5 : datetime 객체 -> datetime.time 객체 변환 후 비교 / x [s] 000000 [us] / sleep 0.001
  • case 6 : datetime 객체 -> datetime.time 객체 변환 후 비교 / x [s] 000000 [us] / sleep 0.001

 

case 3과 case 4에서 x[s]와 x-1[s] 의 경우 클래스 속성 비교 시 조건문의 길이 차이가 생기기에 이것이 반영이 되는가를 판단하기 위해 넣어보았다. 물론 case 1, case 2, case 5, case 6은 해당사항이 없을 것이지만 차이를 같이 보고자 넣었다.

아래 코드는 case 1의 결과를 산출하기 위한 코드이다.

import datetime
import time

def calc(datas):
    mean = 0
    for data in datas:
        if data >= 900000:
            data = data - 1000000
        mean = mean + data
    
    return mean / len(datas)


case_1 = []

for i in range(50):
    # microsecond 0 / compare datetime 
    base = datetime.datetime.now().replace(microsecond=0) + datetime.timedelta(seconds=2)
    while True:
        now = datetime.datetime.now()
        if now >= base:
            break
        else:
            time.sleep(0.001)
    case_1.append(now.microsecond)
    print('case_1 : ' + str(i))
print('case_1 done')
print('1 result : {0}'.format(calc(case_1)))

 

 

1. base는 비교하고자 하는 시간에서 +2[s]를 해준다. (case {짝수}의 경우 +1[s], 999000[us]로 셋팅)

2. now는 현재 시간을 받는다. 

3. 둘을 비교한다. (객체끼리의 비교, class 속성 비교가 나뉜다.)

4. 50번 수행하여 calc에서 평균값 산출

 

결과는 다음과 같다.

 

[각 case에 따른 지연시간 (0 기준)]

 

datetime 모듈이 최적화가 잘되어있기 때문에 객체끼리 비교(case 1, case 2)한 것이 가장 빠른 속도를 보였다. case 4의 경우 x-1[s]와 999000[us]가 and 연산으로 묶여있기 때문에 그 case를 잡지 못한 경우를 보완하는 비교문을 하나 추가하고, 이를 수행하는 시간이 더 걸리므로 case 3보다 시간이 더 걸린 듯하다.

 

어쨌든 datetime 모듈을 그냥 비교하는게 가장 빠른 속도를 보이고 코드도 간편하다.

time.sleep을 하지않고 datetime 모듈 비교하는 경우 속도는 다음과 같다.

-499.4 [us]

프로세서는 바쁘게 일을 하겠지만 정확한 시간에 클릭 한번 하는 프로그램이므로 딱히 문제는 없을 것 같다.

 

 

+ 사족

time.sleep(0.0005)를 하면 나오는 값은 -11.32 로 오히려 시간이 더 지연된다. 이유는 잘 모르겠지만 파이썬 time.sleep 함수의 입력값이 너무 작아서 생기는 문제 같다.

Comments