더 빠른 일반 연산자(예: <, >, =)입니까, 아니면 (-lt, -gt, -eq)를 사용하는 것입니까? 왜?

더 빠른 일반 연산자(예: <, >, =)입니까, 아니면 (-lt, -gt, -eq)를 사용하는 것입니까? 왜?

어느 것이 더 빨리 작동합니까 - 일반 연산자(예: <, >, =)또는 사용(-lt, -gt, -eq)? 왜?

답변1

간단히 명령을 사용하여 이러한 연산자의 성능을 비교할 수 있습니다 time.

time [ 1 -eq 0 ] real 0m0.000s user 0m0.000s sys 0m0.000s

time [ 1 = 0 ] real 0m0.000s user 0m0.000s sys 0m0.000s

이는 다음을 real의미합니다.벽 시계시간과 user수단사용자 공간시간과 sys수단시스템 또는 커널시간.

time이제 이러한 연산자를 다음 줄이 포함된 스크립트의 외부 명령 과 비교하면 비슷한 출력이 표시됩니다.

Sepahrad@localhost 15:17:13 [~]$cat test.sh

#!/bin/bash [ 1 -eq 0 ] echo $?

Sepahrad@localhost 15:17:13 [~]$cat test1.sh

#!/bin/bash [ 1 == 0 ] echo $?

이제 외부 time명령을 실행하면 비슷한 출력이 다시 표시됩니다.

/usr/bin/time ./test.sh또는/usr/bin/time ./test1.sh

1 0.00user 0.00system 0:00.00elapsed 50%CPU (0avgtext+0avgdata 4752maxresident)k 0inputs+0outputs (0major+331minor)pagefaults 0swaps

이제 명령의 소스 코드를 살펴보겠습니다. (소스 코드는 bash다음에서 찾을 수 있습니다.bashhttp://www.gnu.org/software/bash/그리고 test.c파일을 보세요)

int
binary_test (op, arg1, arg2, flags)
     char *op, *arg1, *arg2;
     int flags;
{
  int patmatch;

  patmatch = (flags & TEST_PATMATCH);

  if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0')))
    return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2));
  else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
    {
#if defined (HAVE_STRCOLL)
      if (shell_compatibility_level > 40 && flags & TEST_LOCALE)
        return ((op[0] == '>') ? (strcoll (arg1, arg2) > 0) : (strcoll (arg1, arg2) < 0));
      else
#endif
        return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
    }
  else if (op[0] == '!' && op[1] == '=' && op[2] == '\0')
    return (patmatch ? patcomp (arg1, arg2, NE) : (STREQ (arg1, arg2) == 0));
  else if (op[2] == 't')
    {
      switch (op[1])
        {
        case 'n': return (filecomp (arg1, arg2, NT));           /* -nt */
        case 'o': return (filecomp (arg1, arg2, OT));           /* -ot */
        case 'l': return (arithcomp (arg1, arg2, LT, flags));   /* -lt */
        case 'g': return (arithcomp (arg1, arg2, GT, flags));   /* -gt */
        }
    }
  else if (op[1] == 'e')
    {
      switch (op[2])
        {
        case 'f': return (filecomp (arg1, arg2, EF));           /* -ef */
        case 'q': return (arithcomp (arg1, arg2, EQ, flags));   /* -eq */
        }
    }
  else if (op[2] == 'e')
    {
      switch (op[1])
        {
        case 'n': return (arithcomp (arg1, arg2, NE, flags));   /* -ne */
        case 'g': return (arithcomp (arg1, arg2, GE, flags));   /* -ge */
        case 'l': return (arithcomp (arg1, arg2, LE, flags));   /* -le */
        }
    }

  return (FALSE);       /* should never get here */
}

-eq다음 줄로 설명된 내용을 볼 수 있습니다 .

case 'q': return (arithcomp (arg1, arg2, EQ, flags));   /* -eq

다음과 같이 해석됩니다 =.

if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0')))
    return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2));

AND > 또는 <연산자는 다음과 같이 해석됩니다.

 else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
    {
#if defined (HAVE_STRCOLL)
      if (shell_compatibility_level > 40 && flags & TEST_LOCALE)
        return ((op[0] == '>') ? (strcoll (arg1, arg2) > 0) : (strcoll (arg1, arg2) < 0));
      else
#endif
        return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
    }

또는 -gt다음 -lt과 같이 해석됩니다.

    case 'l': return (arithcomp (arg1, arg2, LT, flags));   /* -lt */
    case 'g': return (arithcomp (arg1, arg2, GT, flags));   /* -gt */

결론: bash소스코드에서 볼 수 있듯이 이들 연산자는 서로 다른 기능으로 설명되어 있지만, 명령어에서 보는 것과 성능이 다르지 않다고 생각합니다 time!

관련 정보