Mon, 07 Nov 2016 18:36:48 -0800 bundle2: use compression engines API to obtain decompressor
Gregory Szorc <gregory.szorc@gmail.com> [Mon, 07 Nov 2016 18:36:48 -0800] rev 30353
bundle2: use compression engines API to obtain decompressor Like the recent change for the compressor side, this too is relatively straightforward. We now store a compression engine on the instance instead of a low-level decompressor. Again, this will allow us to easily transition to different compression engine APIs when they are implemented.
Mon, 07 Nov 2016 18:34:51 -0800 util: remove compressors dict (API)
Gregory Szorc <gregory.szorc@gmail.com> [Mon, 07 Nov 2016 18:34:51 -0800] rev 30352
util: remove compressors dict (API) We no longer have any in-tree consumers of this object. Use util.compengines instead.
Mon, 07 Nov 2016 18:35:43 -0800 bundle2: use new compression engine API for compression
Gregory Szorc <gregory.szorc@gmail.com> [Mon, 07 Nov 2016 18:35:43 -0800] rev 30351
bundle2: use new compression engine API for compression Now that we have a new API to define compression engines, let's put it to use! The new code stores a reference to the compression engine instead of a low-level compressor object. This will allow us to more easily transition to different APIs on the compression engine interface once we implement them. As part of this, we change the registration in bundletypes to use 'UN' instead of None. Previously, util.compressors had the no-op compressor registered under both the 'UN' and None keys. Since we're switching to a new API, I don't see the point in carrying this dual registration forward.
Mon, 07 Nov 2016 18:31:39 -0800 util: create new abstraction for compression engines
Gregory Szorc <gregory.szorc@gmail.com> [Mon, 07 Nov 2016 18:31:39 -0800] rev 30350
util: create new abstraction for compression engines Currently, util.py has "compressors" and "decompressors" dicts mapping compression algorithms to callables returning objects that perform well-defined operations. In addition, revlog.py has code for calling into a compressor or decompressor explicitly. And, there is code in the wire protocol for performing zlib compression. The 3rd party lz4revlog extension has demonstrated the utility of supporting alternative compression formats for revlog storage. But it stops short of supporting lz4 for bundles and the wire protocol. There are also plans to support zstd as a general compression replacement. So, there appears to be a market for a unified API for registering compression engines. This commit starts the process of establishing one. This commit establishes a base class/interface for defining compression engines and how they will be used. A collection class to hold references to registered compression engines has also been introduced. The built-in zlib, bz2, truncated bz2, and no-op compression engines are registered with a singleton instance of the collection class. The compression engine API will change once consumers are ported to the new API and some common patterns can be simplified at the engine API level. So don't get too attached to the API...
Sun, 09 Oct 2016 09:25:39 -0400 config: mark parser regexes as bytes explicitly
Augie Fackler <augie@google.com> [Sun, 09 Oct 2016 09:25:39 -0400] rev 30349
config: mark parser regexes as bytes explicitly r-strings are not transformed into bytes by our source transformer magic.
Sun, 09 Oct 2016 09:17:49 -0400 ui: explicitly open config files in binary mode
Augie Fackler <augie@google.com> [Sun, 09 Oct 2016 09:17:49 -0400] rev 30348
ui: explicitly open config files in binary mode This has been working mostly accidentally, but now it works explicitly.
Wed, 09 Nov 2016 16:04:44 -0800 help: fix double word usage
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 09 Nov 2016 16:04:44 -0800] rev 30347
help: fix double word usage "most" was used twice. (I fixed a grammar error before timeless spotted it!)
Wed, 09 Nov 2016 22:08:30 +0000 setup: move cffi stuff to mercurial/cffi
Jun Wu <quark@fb.com> [Wed, 09 Nov 2016 22:08:30 +0000] rev 30346
setup: move cffi stuff to mercurial/cffi This patch moves all setup*cffi stuff to mercurial/cffi to make the root directory cleaner. The idea was from mpm [1]: > It seems like we could have a fair amount of cffi definitions, and > cluttering the root directory (or mercurial/) with them is probably not > a great long-term solution. We could probably add a cffi/ directory > under mercurial/ to parallel pure/. [1]: https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-July/086442.html
Tue, 08 Nov 2016 08:03:43 -0800 manifest: remove manifest.add and add memmfctx.write
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30345
manifest: remove manifest.add and add memmfctx.write This removes one more dependency on the manifest class by moving the write functionality onto the memmanifestctx classes and changing the one consumer to use the new API. By moving the write path to a manifestctx, we now give the individual manifests control over how they're read and serialized. This will be useful in developing new manifest formats and storage systems.
Tue, 08 Nov 2016 08:03:43 -0800 context: add manifestctx property on changectx
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30344
context: add manifestctx property on changectx This allows us to access the manifestctx for a given commit. This will be used in a later patch to be able to copy the manifestctx when we want to make a new commit.
Tue, 08 Nov 2016 08:03:43 -0800 manifest: add copy to mfctx classes
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30343
manifest: add copy to mfctx classes This adds copy functionality to the manifestctx classes. This will be used in an upcoming diff to copy a manifestctx during commit so we can modify the manifest before committing.
Tue, 08 Nov 2016 08:03:43 -0800 manifest: introduce memmanifestctx and memtreemanifestctx
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30342
manifest: introduce memmanifestctx and memtreemanifestctx This introduces two new classes to represent in-memory manifest instances. Similar to memchangectx, this lets us prepare a manifest in memory, then in a future patch we will add the apis that can commit this in memory structure.
Tue, 08 Nov 2016 08:03:43 -0800 manifestctx: add _revlog() function
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30341
manifestctx: add _revlog() function The `self._repo.manifestlog._revlog` code is getting copy and pasted a lot in manifestctx. Let's make it a function so it can be reused. This will make future patches cleaner too.
Tue, 08 Nov 2016 08:03:43 -0800 manifest: remove manifest.find
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30340
manifest: remove manifest.find As part of removing dependencies on manifest, this drops the find function and fixes up the two existing callers to use the equivalent apis on manifestctx.
Tue, 08 Nov 2016 08:03:43 -0800 changegroup: remove remaining uses of repo.manifest
Durham Goode <durham@fb.com> [Tue, 08 Nov 2016 08:03:43 -0800] rev 30339
changegroup: remove remaining uses of repo.manifest The remaining uses of repo.manifest in the changegroup module are treating the manifest exclusively as a revlog, so let's replace them with instances of the revlog directly. This is part of dropping all dependencies on repo.manifest in favor of repo.manifestlog.
Fri, 04 Nov 2016 13:49:15 -0700 treemanifest: fix a "treeinmem" case
Martin von Zweigbergk <martinvonz@google.com> [Fri, 04 Nov 2016 13:49:15 -0700] rev 30338
treemanifest: fix a "treeinmem" case f2c5b9d48b29 (manifest: make treemanifestctx store the repo, 2016-10-18) broke most tests when run with treeinmem=True. The treeinmem mode can not be enabled by the user, so this did not break anything in practice, but it's useful to have it working for testing the treemanifest code.
Sun, 06 Nov 2016 10:46:55 -0800 perf: support measuring bdiff for all changeset related data
Gregory Szorc <gregory.szorc@gmail.com> [Sun, 06 Nov 2016 10:46:55 -0800] rev 30337
perf: support measuring bdiff for all changeset related data The --all argument changes the behavior of `perfbdiff` to pull in fulltext revision pairs for all changes related to a changeset. The p1 and p2 manifests will be bdiffed against current. Every file that changed between p1 and current will have its file revisions loaded and bdiffed. This mode of operation effectively measured the bdiff time required for `hg commit`.
Sun, 06 Nov 2016 11:01:25 -0800 perf: support bdiffing multiple revisions in a single revlog
Gregory Szorc <gregory.szorc@gmail.com> [Sun, 06 Nov 2016 11:01:25 -0800] rev 30336
perf: support bdiffing multiple revisions in a single revlog This is useful for testing bdiff performance on several revision pairs at a time.
Sun, 06 Nov 2016 09:51:14 -0800 perf: prepare to handle multiple pairs in perfbdiff
Gregory Szorc <gregory.szorc@gmail.com> [Sun, 06 Nov 2016 09:51:14 -0800] rev 30335
perf: prepare to handle multiple pairs in perfbdiff Before, we only supported benchmarking a single pair of texts with bdiff. We want to enable feeding larger corpora into this benchmark. So rewrite the code to support that.
Wed, 09 Nov 2016 22:06:09 +0900 py3: document why os.fsencode() can be used to get back bytes argv
Yuya Nishihara <yuya@tcha.org> [Wed, 09 Nov 2016 22:06:09 +0900] rev 30334
py3: document why os.fsencode() can be used to get back bytes argv And a possible Windows issue. I'm sad we have to do such ugly hack, but that's the unicode on Python 3.
Wed, 09 Nov 2016 22:15:51 +0900 py3: update test-check-py3-compat.t output
Yuya Nishihara <yuya@tcha.org> [Wed, 09 Nov 2016 22:15:51 +0900] rev 30333
py3: update test-check-py3-compat.t output 4b1af1c867fa (scmutil: move util.termwidth()) changed where the import fails.
Mon, 17 Oct 2016 23:16:55 +0200 spelling: fixes of non-dictionary words
Mads Kiilerich <madski@unity3d.com> [Mon, 17 Oct 2016 23:16:55 +0200] rev 30332
spelling: fixes of non-dictionary words
Thu, 03 Nov 2016 17:31:14 -0700 manifest: add __nonzero__ method
Durham Goode <durham@fb.com> [Thu, 03 Nov 2016 17:31:14 -0700] rev 30331
manifest: add __nonzero__ method This adds a __nonzero__ method to manifestdict. This isn't strictly necessary in the vanilla Mercurial implementation, since Python will handle nonzero checks by using __len__, but having it implemented here makes it easier for alternative implementations to implement __nonzero__ and have them be plug-n-play with the normal implementation.
Sun, 06 Nov 2016 04:36:26 +0530 py3: have bytes version of sys.argv
Pulkit Goyal <7895pulkit@gmail.com> [Sun, 06 Nov 2016 04:36:26 +0530] rev 30330
py3: have bytes version of sys.argv sys.argv returns unicodes on Python 3. We need a bytes version for us. There was also a python bug/feature request which wanted then to implement one. They rejected and it is quoted in one of the comments that we can use fsencode() to get a bytes version of sys.argv. Though not sure about its correctness. Link to the comment: http://bugs.python.org/issue8776#msg217416 After this patch we will have pycompat.sysargv which will return us bytes version of sys.argv. If this patch goes in, i will like to make transformer rewrite sys.argv with pycompat.argv because there are lot of occurences.
Sun, 09 Oct 2016 09:00:47 -0400 util: use '\\' rather than using r'\'
Augie Fackler <augie@google.com> [Sun, 09 Oct 2016 09:00:47 -0400] rev 30329
util: use '\\' rather than using r'\' We need bytes, and I find this just a little more immediately obvious than doing rb'\'.
Sun, 09 Oct 2016 09:03:10 -0400 util: use pycompat urlunquote function
Augie Fackler <augie@google.com> [Sun, 09 Oct 2016 09:03:10 -0400] rev 30328
util: use pycompat urlunquote function
Sun, 09 Oct 2016 09:02:25 -0400 pycompat: introduce an alias for urllib.unquote
Augie Fackler <augie@google.com> [Sun, 09 Oct 2016 09:02:25 -0400] rev 30327
pycompat: introduce an alias for urllib.unquote We have to use unquote_to_bytes on Python 3, so we need an abstraction for this.
Mon, 17 Oct 2016 17:42:46 +0200 keyword: handle filectx _customcmp
Christian Ebert <blacktrash@gmx.net> [Mon, 17 Oct 2016 17:42:46 +0200] rev 30326
keyword: handle filectx _customcmp Suggested by Yuya Nishihara: https://www.mercurial-scm.org/pipermail/mercurial-devel/2016-October/089461.html Related to issue5364.
Thu, 20 Oct 2016 22:20:31 +0900 mail: do not print(), use ui.debug() instead
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 22:20:31 +0900] rev 30325
mail: do not print(), use ui.debug() instead Since print() can't take a bytes output, it's pretty useless in Mercurial on Python 3. As this is a debug message, switching to ui.debug() seems fine.
Thu, 20 Oct 2016 22:12:48 +0900 progress: obtain stderr from ui
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 22:12:48 +0900] rev 30324
progress: obtain stderr from ui This will help Python 3 porting.
Thu, 20 Oct 2016 22:09:50 +0900 simplemerge: obtain stdout from ui
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 22:09:50 +0900] rev 30323
simplemerge: obtain stdout from ui This will help Python 3 porting.
Thu, 20 Oct 2016 22:07:03 +0900 profiling: obtain stderr from ui
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 22:07:03 +0900] rev 30322
profiling: obtain stderr from ui This will help Python 3 porting.
Sun, 13 Nov 2016 06:12:22 +0900 scmutil: ignore EPERM at os.utime, which avoids ambiguity at closing stable
FUJIWARA Katsunori <foozy@lares.dti.ne.jp> [Sun, 13 Nov 2016 06:12:22 +0900] rev 30321
scmutil: ignore EPERM at os.utime, which avoids ambiguity at closing According to POSIX specification, just having group write access to a file causes EPERM at invocation of os.utime() with an explicit time information (e.g. working on the repository shared by group access permission). To ignore EPERM at closing file object in such case, this patch makes checkambigatclosing._checkambig() use filestat.avoidambig() introduced by previous patch. Some functions below imply this code path at truncation of an existing (= might be owned by another user) file. - strip() in repair.py, introduced by e38d85be978f - _playback() in transaction.py, introduced by 599912a62ff6 This is a variant of issue5418.
Sun, 13 Nov 2016 06:11:56 +0900 vfs: ignore EPERM at os.utime, which avoids ambiguity at renaming (issue5418) stable
FUJIWARA Katsunori <foozy@lares.dti.ne.jp> [Sun, 13 Nov 2016 06:11:56 +0900] rev 30320
vfs: ignore EPERM at os.utime, which avoids ambiguity at renaming (issue5418) According to POSIX specification, just having group write access to a file causes EPERM at invocation of os.utime() with an explicit time information (e.g. working on the repository shared by group access permission). To ignore EPERM at renaming in such case, this patch makes vfs.rename() use filestat.avoidambig() introduced by previous patch.
Sun, 13 Nov 2016 06:06:23 +0900 util: add utility function to skip avoiding file stat ambiguity if EPERM stable
FUJIWARA Katsunori <foozy@lares.dti.ne.jp> [Sun, 13 Nov 2016 06:06:23 +0900] rev 30319
util: add utility function to skip avoiding file stat ambiguity if EPERM Now, advancing stat.st_mtime by os.utime() is used to avoid file stat ambiguity. But according to POSIX specification, utime(2) with an explicit time information is permitted only for a process with: - the effective user ID equal to the user ID of the file, or - appropriate privileges http://pubs.opengroup.org/onlinepubs/9699919799/functions/utime.html Therefore, just having group write access to a file causes EPERM at applying os.utime() on it (e.g. working on the repository shared by group access permission). This patch adds class filestat utility function avoidamgig() to avoid file stat ambiguity but skip it if EPERM. It is reasonable to always ignore EPERM, because utime(2) causes EPERM only in the case described above (EACCES is used only for utime(2) with NULL).
Sun, 06 Nov 2016 18:51:57 -0800 bdiff: replace hash algorithm
Gregory Szorc <gregory.szorc@gmail.com> [Sun, 06 Nov 2016 18:51:57 -0800] rev 30318
bdiff: replace hash algorithm This patch replaces lyhash with the hash algorithm used by diffutils. The algorithm has its origins in Git commit 2e9d1410, which is all the way back from 1992. The license header in the code at that revision in GPL v2. I have not performed an extensive analysis of the distribution (and therefore buckets) of hash output. However, `hg perfbdiff` gives some clear wins. I'd like to think that if it is good enough for diffutils it is good enough for us? From the mozilla-unified repository: $ perfbdiff -m 3041e4d59df2 ! wall 0.053271 comb 0.060000 user 0.060000 sys 0.000000 (best of 100) ! wall 0.035827 comb 0.040000 user 0.040000 sys 0.000000 (best of 100) $ perfbdiff 0e9928989e9c --alldata --count 100 ! wall 6.204277 comb 6.200000 user 6.200000 sys 0.000000 (best of 3) ! wall 4.309710 comb 4.300000 user 4.300000 sys 0.000000 (best of 3) From the hg repo: $ perfbdiff 35000 --alldata --count 1000 ! wall 0.660358 comb 0.660000 user 0.660000 sys 0.000000 (best of 15) ! wall 0.534092 comb 0.530000 user 0.530000 sys 0.000000 (best of 19) Looking at the generated assembly and statistical profiler output from the kernel level, I believe there is room to make this function even faster. Namely, we're still consuming data character by character instead of at the word level. This translates to more loop iterations and more instructions. At this juncture though, the real performance killer is that we're hashing every line. We should get a significant speedup if we change the algorithm to find the longest prefix, longest suffix, treat those as single "lines" and then only do the line splitting and hashing on the parts that are different. That will require a lot of C code, however. I'm optimistic this approach could result in a ~2x speedup.
Fri, 04 Nov 2016 21:44:25 -0700 profiling: make statprof the default profiler (BC)
Gregory Szorc <gregory.szorc@gmail.com> [Fri, 04 Nov 2016 21:44:25 -0700] rev 30317
profiling: make statprof the default profiler (BC) The statprof sampling profiler runs with significantly less overhead. Its data is therefore more useful. Furthermore, its default output shows the hotpath by default, which I've found to be way more useful than the default profiler's function time table. There is one behavioral regression with this change worth noting: the statprof profiler currently doesn't profile individual hgweb requests like lsprof does. This is because the current implementation of statprof only profiles the thread that started profiling. The ability for lsprof to profile individual hgweb requests is relatively new and likely not widely used. Furthermore, I have plans to modify statprof to support profiling multiple threads. I expect that change to go through several iterations. I'm submitting this patch first so there is more time to test statprof. Perfect is the enemy of good.
Fri, 04 Nov 2016 20:50:38 -0700 profiling: use vendored statprof and upstream enhancements (BC)
Gregory Szorc <gregory.szorc@gmail.com> [Fri, 04 Nov 2016 20:50:38 -0700] rev 30316
profiling: use vendored statprof and upstream enhancements (BC) Now that the statprof module is vendored and suitable for use, we switch our statprof profiler to use it. This required some minor changes because of drift between the official statprof profiler and the vendored copy. We also incorporate Facebook's improvements from the "statprofext" extension at https://bitbucket.org/facebook/hg-experimental, notably support for different display formats. Because statprof output is different, this is marked as BC. Although most users likely won't notice since most users don't profile.
Thu, 20 Oct 2016 23:16:32 +0900 crecord: use scmutil.termsize()
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 23:16:32 +0900] rev 30315
crecord: use scmutil.termsize()
Thu, 20 Oct 2016 23:09:05 +0900 scmutil: extend termwidth() to return terminal height, renamed to termsize()
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 23:09:05 +0900] rev 30314
scmutil: extend termwidth() to return terminal height, renamed to termsize() It appears crecord.py has its own termsize() function. I want to get rid of it. The fallback height is chosen from the default of cmd.exe on Windows, and VT100 on Unix.
Thu, 20 Oct 2016 22:57:12 +0900 scmutil: clarify that we explicitly do termwidth - 1 on Windows
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 22:57:12 +0900] rev 30313
scmutil: clarify that we explicitly do termwidth - 1 on Windows I was a bit confused since we didn't add 1 to the width, which is different from the example shown in StackOverflow. http://stackoverflow.com/a/12642749
Thu, 20 Oct 2016 21:57:32 +0900 scmutil: remove superfluous indent from termwidth()
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 21:57:32 +0900] rev 30312
scmutil: remove superfluous indent from termwidth()
Thu, 20 Oct 2016 21:50:29 +0900 scmutil: narrow ImportError handling in termwidth()
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 21:50:29 +0900] rev 30311
scmutil: narrow ImportError handling in termwidth() The array module must exist. It's sufficient to suppress the ImportError of termios. Also salvaged the comment why we have to handle AttributeError, from 7002bb17cc5e.
Thu, 20 Oct 2016 21:42:11 +0900 scmutil: make termwidth() obtain stdio from ui
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 21:42:11 +0900] rev 30310
scmutil: make termwidth() obtain stdio from ui I'm getting rid of direct sys.stderr|out|in references so Py3 porting will be slightly easier.
Thu, 20 Oct 2016 21:38:44 +0900 scmutil: move util.termwidth()
Yuya Nishihara <yuya@tcha.org> [Thu, 20 Oct 2016 21:38:44 +0900] rev 30309
scmutil: move util.termwidth() I'm going to get rid of sys.stderr|out|in references from posix.termwidth(). In order to do that, termwidth() needs to take a ui, but functions in util.py shouldn't depend on a ui object. So moves termwidth() to scmutil.py.
Sun, 06 Nov 2016 00:37:50 -0700 bdiff: don't check border condition in loop
Gregory Szorc <gregory.szorc@gmail.com> [Sun, 06 Nov 2016 00:37:50 -0700] rev 30308
bdiff: don't check border condition in loop `plast = a + len - 1`. So, this "for" loop iterates from "a" to "plast", inclusive. So, `p == plast` can only be true on the final iteration of the loop. So checking for it on every loop iteration is wasteful. This patch simply decreases the upper bound of the loop by 1 and adds an explicit check after iteration for the `p == plast` case. We can't simply add 1 to the initial value for "i" because that doesn't do the correct thing on empty input strings. `perfbdiff -m 3041e4d59df2` on the Firefox repo becomes significantly faster: ! wall 0.072763 comb 0.070000 user 0.070000 sys 0.000000 (best of 100) ! wall 0.053221 comb 0.060000 user 0.060000 sys 0.000000 (best of 100) For the curious, this code has its origins in 8b067bde6679, which is the changeset that introduced bdiff.c in 2005. Also, GNU diffutils is able to perform a similar line-based diff in under 20ms. So there's likely more perf wins to be found in this code. One of them is the hashing algorithm. But it looks like mpm spent some time testing hash collisions in d0c48891dd4a. I'd like to do the same before switching away from lyhash, just to be on the safe side.
Sat, 05 Nov 2016 23:41:52 -0700 perf: add perfbdiff
Gregory Szorc <gregory.szorc@gmail.com> [Sat, 05 Nov 2016 23:41:52 -0700] rev 30307
perf: add perfbdiff bdiff shows up a lot in profiling. I think it would be useful to have a perf command that runs bdiff over and over so we can find hot spots.
Sun, 06 Nov 2016 06:54:31 +0530 help: show help for disabled extensions (issue5228)
Pulkit Goyal <7895pulkit@gmail.com> [Sun, 06 Nov 2016 06:54:31 +0530] rev 30306
help: show help for disabled extensions (issue5228) This patch does not exactly solve issue5228 but it results in a better condition on this issue. For disabled extensions, we used to parse the module and get the first occurrences of docstring and then return the first line of that as an introductory heading of extension. This is what we get today. This patch returns the whole docstring of the module as a help for extension, which is more informative. There are some modules which don't have much docstring at top level except the heading so those are unaffected by this change. To follow the existing trend of showing commands either we have to load the extension or have a very ugly parsing method which don't even assure correctness.
(0) -30000 -10000 -3000 -1000 -300 -100 -48 +48 +100 +300 +1000 +3000 +10000 tip