SORU
10 AĞUSTOS 2015, PAZARTESİ


Neden string'daha yavaş daha startswith s?

Şaşırtıcı olan, startswith in daha yavaş olduğunu düşünüyorum:

In [10]: s="ABCD"*10

In [11]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 307 ns per loop

In [12]: %timeit "XYZ" in s
10000000 loops, best of 3: 81.7 ns per loop

Hepimizin bildiği gibi, in işlemi tüm dizeyi aramak için ihtiyaçları ve startswith sadece ilk birkaç karakteri kontrol gerekir startswith daha etkili olur.

s yeterince büyük olduğunda, startswith daha hızlı

In [13]: s="ABCD"*200

In [14]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 306 ns per loop

In [15]: %timeit "XYZ" in s
1000000 loops, best of 3: 666 ns per loop

startswith arama dize küçük olduğunda daha yavaş olur biraz masrafı var gibi görünüyor.

Ve startswith çağrı yükü ne olduğunu anlamaya çalıştım.

İlk olarak, bu answer burada startswith hala yavaş olduğunu görüyoruz belirtildiği gibi f değişken nokta operasyon maliyeti azaltmak için kullanılır:

In [16]: f=s.startswith

In [17]: %timeit f("XYZ")
1000000 loops, best of 3: 270 ns per loop

Ayrıca, boş bir fonksiyon çağrısı maliyeti test:

In [18]: def func(a): pass

In [19]: %timeit func("XYZ")
10000000 loops, best of 3: 106 ns per loop

Nokta operasyonu ve fonksiyonun maliyeti ne olursa olsun, startswith zaman=164ns, ama in Bu çalışma, sadece 81.7 ns alır (270-106). Hala ne startswith için bazı giderleri var gibi görünüyor?

Test poke ve lvc önerdiği gibi startswith __contains__ arasında neden ekleyin:

In [28]: %timeit s.startswith("XYZ")
1000000 loops, best of 3: 314 ns per loop

In [29]: %timeit s.__contains__("XYZ")
1000000 loops, best of 3: 192 ns per loop

CEVAP
10 AĞUSTOS 2015, PAZARTESİ


Zaten belirtildiği açıklamalarda, eğer kullandığınız s.__contains__("XYZ") olsun sonuç daha benzer s.startswith("XYZ") çünkü ihtiyaçları aynı rota: Üye arama dize nesne, ardından bir işlev çağrısı. Bu genellikle biraz pahalı (tabi endişelenmen gereken bu yeterli değil). Diğer taraftan, ne zaman yap "XYZ" in s çözümleyici yorumlar operatörü ve kısa kesilmiş üye __contains__ (ya da daha doğrusu uygulama arkasında, çünkü __contains__ kendisi sadece bir şekilde erişim uygulaması).

Bayt kodu bakarak bu konuda bir fikir edinebilirsiniz:

>>> dis.dis('"XYZ" in s')
  1           0 LOAD_CONST               0 ('XYZ')
              3 LOAD_NAME                0 (s)
              6 COMPARE_OP               6 (in)
              9 RETURN_VALUE
>>> dis.dis('s.__contains__("XYZ")')
  1           0 LOAD_NAME                0 (s)
              3 LOAD_ATTR                1 (__contains__)
              6 LOAD_CONST               0 ('XYZ')
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 RETURN_VALUE

Yani s.startswith("XYZ") 34 *karşılaştırma daha benzer bir sonuç, ancak s, startswith hala daha yavaş olacaktır örnek dizesi için üretecek.

Onun için, hem de uygulanması kontrol edebilir. Statik olarak yazılan ve bağımsız bir unicode olduğunu varsayar contains implementation görmek ilginç nesne kendisini. Bu oldukça verimlidir.

startswith implementation ancak bu bir “dinamik” uygulama aslında argümanlar ayrıştırma gerektiren Python yöntemi. startswith tüm devreye alma yöntemi biraz daha yavaş yapar, bağımsız değişken olarak bir demet destekler: (bana göre kısaltılmış, yorumlarım ile):

static PyObject * unicode_startswith(PyObject *self, PyObject *args)
{
    // argument parsing
    PyObject *subobj;
    PyObject *substring;
    Py_ssize_t start = 0;
    Py_ssize_t end = PY_SSIZE_T_MAX;
    int result;
    if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
        return NULL;

    // tuple handling
    if (PyTuple_Check(subobj)) {}

    // unicode conversion
    substring = PyUnicode_FromObject(subobj);
    if (substring == NULL) {}

    // actual implementation
    result = tailmatch(self, substring, start, end, -1);
    Py_DECREF(substring);
    if (result == -1)
        return NULL;
    return PyBool_FromLong(result);
}

Bu büyük olasılıkla startswith contains bir hızlı, basit olduğu dizeleri yavaş neden büyük bir nedenidir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Besnik Ibrahimi

    Besnik Ibrah

    27 Mart 2010
  • Random Act of Kindness Video Contest

    Random Act o

    18 EYLÜL 2012
  • Ownage Pranks

    Ownage Prank

    13 AĞUSTOS 2007