엄격한 코드 1: 불변성이 나빠질 때

7253 단어 reactwebdevjavascript
이것은 중요할 때 성능이 뛰어난 Javascript 코드를 작성하는 방법을 살펴보는 시리즈의 첫 번째 기사입니다. 코드를 작성할 때 코드가 사용되는 위치와 효과에 대해 생각해야 합니다. 적은 양의 데이터로 작업하면 많은 비효율성을 피할 수 있지만, 머지 않아 여러분이 작성한 아름다운 코드가 여러분을 깨물게 될 것입니다. 중요한 것은 많은 데이터를 처리하거나 자주 실행되는 루프 내부를 스크립팅할 때입니다. 이 시리즈는 이러한 상황에서 비용이 많이 드는 실수를 발견하고 피하는 데 도움을 주는 것을 목표로 합니다.

불변성을 보자. 그것은 거의 만트라가 되었습니다. 아마도 배열을 변경하는 것이 더럽다고 느껴야 할까요? 항상 그렇지 않은 이유를 설명하겠습니다.
  • 새 개체를 생성하면 메모리가 할당됩니다
  • .
  • 메모리 할당에 시간이 걸림
  • 할당할 때 가비지 수집에 시간이 걸리므로 결함이 발생함
  • 가비지 컬렉션은 방금 할당한 항목을 제거하는 데 시간이 걸립니다
  • .

    공유할 수 있는 상태를 더 쉽게 관리할 수 있기 때문에 일반적으로 불변성을 사용합니다. 올바른 변수가 있는지 쉽게 확인하기 위해 Typescript를 사용하는 것과 약간 비슷하지 않습니까? 아니오. 코드를 실행할 때 Typescript는 사라지고 이러한 메모리 할당은 사용자에게 계속해서 영향을 미칩니다.

    배열의 길이가 20개 항목이고 자주 변경되지 않는 경우 이제 이 중 아무 것도 중요하지 않습니다. 그렇지 않은 곳이 있을 수도 있습니다. 저도 알고 있습니다.

    반응 상태



    렌더러에서 무언가에 사용할 React에 배열이 있다고 가정해 봅시다. 가상 목록에 결과를 붙일 수 있습니다. 사용자가 항목을 추가할 수 있고 다른 사용자가 항목을 추가할 수 있다고 가정해 보겠습니다. 이것이 채팅이라고 가정 해 봅시다! 자, 우리가 무언가를 추가할 수 있고 네트워크가 무언가를 추가할 수 있습니다. 이에 대한 이벤트 이미터가 있다고 가정해 봅시다.

    
    function Chat() {
        const [messages, setMessages] = useState([])
        useEffect(()=>{
             someEventEmitter.on("newMessage", addMessage);
             return ()=>someEventEmitter.off("newMessage", addMessage);
        }, [])
        return <VirtualList items={messages}>
           {message=><Message details={message}/>}
        </VirtualList>
    
        function addMessage(message) {
            setMessages([...messages, message]);
        }
    }
    
    


    아름다운 불변의 메시지. 우. 조심해. 얼마나 비쌉니까?

    당신이 갑자기 인기를 얻었다고 가정해 봅시다. 또는 당신이 주가 등의 라이브 피드를 받기로 결정했다고 가정해 봅시다. 얼마 동안 거기에 10,000개의 메시지가 있다고 가정해 봅시다. 각 메시지의 길이가 대략 140자라고 가정해 보겠습니다. utf8이고 140바이트라고 가정해 보겠습니다.

    얼마나 많은 메모리를 할당했는지 짐작이 가십니까? 최종 목록은 무려 1.4mb입니다. 하지만 그 과정에서 얼마나 할당했습니까? 추측해 보세요... 정답은 7GB입니다. 가까이 있었나요? 7GB. 결함을 상상할 수 있습니까? 하지만 적어도 당신은 불변성을 유지했습니다. 휴, 누군가가 그 목록을 사용할 수 있었기 때문입니다. 그 목록은 지역적이었습니다. 배열을 ref에 보관하고 변경했을 수 있습니다(내가 다시 변경한다고 말한 것을 참조하십시오. X 등급 게시물!)

    
    function Chat() {
        const [, refresh] = useState(0)
        const messages = useRef([])
        useEffect(()=>{
             someEventEmitter.on("newMessage", addMessage);
             return ()=>someEventEmitter.off("newMessage", addMessage);
        }, [])
        return <VirtualList items={messages.current}>
           {message=><Message details={message}/>
        </VirtualList>
    
        function addMessage(message) {
            //Don't look mum
            messages.current.push(message)
            //Get the whole thing to render again
            refresh(performance.now())
        }
    }
    
    


    메모리 불변성의 99.98%를 약간 절약하면 비용이 발생합니다.

    결론



    나는 불변성이 항상 나쁘다고 말하는 것이 아닙니다. 분명히 그렇지 않습니다. 그러나 그것을 잘못 사용하여 혼란에 빠지는 것은 무섭도록 쉽습니다.

    이 예제는 메모리에 초점을 맞추었지만 성능은 또 다른 문제입니다.

    불변성을 사용하여 배열에 10,000개의 정수를 얼마나 빨리 추가할 수 있습니까?



    가장 빠른 방법을 원한다면 초당 85,000번, push로 26,000번, errr.... 스프레드 연산자로 20번. 그냥 말해

    좋은 웹페이지 즐겨찾기