Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(319)

Side by Side Diff: src/pkg/net/textproto/reader.go

Issue 6843056: code review 6843056: net/http, net/textproto: cache common header values (Closed)
Patch Set: diff -r 591fc8a0131a https://code.google.com/p/go Created 11 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/net/textproto/reader_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 The Go Authors. All rights reserved. 1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package textproto 5 package textproto
6 6
7 import ( 7 import (
8 "bufio" 8 "bufio"
9 "bytes" 9 "bytes"
10 "io" 10 "io"
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 for endKey > 0 && kv[endKey-1] == ' ' { 463 for endKey > 0 && kv[endKey-1] == ' ' {
464 endKey-- 464 endKey--
465 } 465 }
466 key := canonicalMIMEHeaderKey(kv[:endKey]) 466 key := canonicalMIMEHeaderKey(kv[:endKey])
467 467
468 // Skip initial spaces in value. 468 // Skip initial spaces in value.
469 i++ // skip colon 469 i++ // skip colon
470 for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') { 470 for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') {
471 i++ 471 i++
472 } 472 }
473 » » value := string(kv[i:]) 473 » » value := theStringCache.get(kv[i:])
474 474
475 m[key] = append(m[key], value) 475 m[key] = append(m[key], value)
476 476
477 if err != nil { 477 if err != nil {
478 return m, err 478 return m, err
479 } 479 }
480 } 480 }
481 panic("unreachable") 481 panic("unreachable")
482 } 482 }
483 483
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 "Server", 583 "Server",
584 "Set-Cookie", 584 "Set-Cookie",
585 "Subject", 585 "Subject",
586 "To", 586 "To",
587 "User-Agent", 587 "User-Agent",
588 "Via", 588 "Via",
589 "X-Forwarded-For", 589 "X-Forwarded-For",
590 "X-Imforwards", 590 "X-Imforwards",
591 "X-Powered-By", 591 "X-Powered-By",
592 } 592 }
593
594 // A stringCache is an array of strings where position X is
595 // occupied by the string of length X. Looks are very fast,
596 // because a lookup consists of at most one string compare.
597 // The miss count is used to decide when to evict an entry that
598 // is not pulling its weight, and should give its spot to a more
599 // common string of the same length.
600 type entry struct {
601 s string
602 miss int
603 }
604
605 // maxCachableLen and maxMisses were chosen by looking at traces of
606 // headers arriving at a real-world webserver.
607 const maxCachableLen = 100
608 const maxMisses = 9
609
610 type stringCache [maxCachableLen]entry
611
612 var theStringCache stringCache
613
614 func eq(x []byte, y string) bool {
615 if len(x) != len(y) {
616 return false
617 }
618
619 for i, b := range x {
620 if y[i] != b {
621 return false
622 }
623 }
624 return true
625 }
626
627 func (sc *stringCache) get(x []byte) string {
628 if len(x) >= len(sc) {
629 return string(x)
630 }
631
632 // grab a private copy of the entry so another thread can't
633 // change it on us
634 it := sc[len(x)]
635
636 // first use of this entry or this entry is missing too
637 // often: set it to string(x)
638 if it.s == "" || it.miss > maxMisses {
639 s := string(x)
640 // this write is racy, but we'll return the right answer
641 // even if we lose the race
642 sc[len(x)].s = s
dvyukov 2012/11/15 11:33:15 That will crash and corrupt memory. Even an "inno
dvyukov 2012/11/15 11:44:16 You can do some shortcuts with sync/atomic package
643 sc[len(x)].miss = 0
644 return s
645 }
646
647 // the write to miss below are racy, but it is approximate
648 // and we don't care if we lose the race.
649 if eq(x, it.s) {
650 sc[len(x)].miss = 0
dvyukov 2012/11/15 11:53:05 You better not update it if it's already 0, it wil
651 return it.s
652 }
653 sc[len(x)].miss++
654 return string(x)
655 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/net/textproto/reader_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b