Skip to content
Snippets Groups Projects
  1. Apr 15, 2021
    • Georges Racinet's avatar
      Setting version for release · df53b71c17a4
      Georges Racinet authored
      0.12.0
      df53b71c17a4
    • Georges Racinet's avatar
      Merged stable branch into default · fb6208acd24f
      Georges Racinet authored
      fb6208acd24f
    • Georges Racinet's avatar
      New stable dev cycle · 065e782d5751
      Georges Racinet authored
      065e782d5751
    • Georges Racinet's avatar
      Added tag 0.11.1 for changeset 39a6480f5501 · 8a8b7f110f21
      Georges Racinet authored
      8a8b7f110f21
    • Georges Racinet's avatar
      Setting version for release · 39a6480f5501
      Georges Racinet authored
      0.11.1
      39a6480f5501
    • Georges Racinet's avatar
      server: mono-process mode · bdd1f208778c
      Georges Racinet authored
      The forking that the `hgitaly-serve` command is doing by
      default is harmful when we want to debug with pdb: request
      handling always end in an error. The new `--mono-process`
      option solves that by serving directly from the main process.
      This is probably a matter of forwarding all the
      right file descriptors for the tty, but it's not worth
      the investigation time when there is such a simple solution.
      
      Could have done it in the command itself, but this is probably
      easier to maintain in the `server` module and certainly easier
      to test.
      
      No strong assertions that it doesn't fork in the test, but
      coverage proves that the early return got executed; that should
      be enough.
      bdd1f208778c
    • Georges Racinet's avatar
      load_repo: fix the class leak for sharedrepo source as well · 58e290c6dbb1
      Georges Racinet authored
      Previous fixes have been developed and measured in a Python 3.9
      virtualenv (HDK). Replaying the measurements in a Python 3.8 HDK
      (the only supported Python version in all current Heptapod branches)
      immediately showed that this wasn't enough.
      
      After reconstruction of the virtualenv with Python 3.8, it became
      obvious that repository instances (and classes) where doubled, and
      the reason was the systematic instantiation of a sharedrepo source.
      Applying the same treatment for the latter got us back to the
      improvement previously obtained.
      
      It seems frankly dubious that the Python version is really
      implicated, but it could happen: we're after all dealing with stuff
      that the GC didn't clear by itself. Still, it could simply have been
      a matter of library version (not Mercurial, it's the same one).
      58e290c6dbb1
    • Georges Racinet's avatar
      load_repo: forcing garbage collection every 1000 calls. · 56bcfbb515df
      Georges Racinet authored
      For something similar with hgweb, look at changeset ff2370a70fe8
      in Mercurial.
      
      Surprisingly, this does not change the memory footprint in our
      current investigations (which is just using examples/client.py
      with more calls). This means that the regular garbage collector
      was able to reap benefits of the parent changeset (calling
      `gc.collect()` is supposed to be more aggressive on the oldest
      generation).
      
      Still, keeping this as a safety net because our example certainly
      wouldn't cover all possible situations
      
      With rates of 100 and 500, the new log lines show us the GC
      working, with more to collect at 500 than at 100. But at 1000,
      we get back to the same amounts of collected objects and time
      spent than with 100. This suggests that this is close to the
      natural rate, hence we aren't really harming performance.
      
      In any case, this is a constant, and we could make it more
      configurable if needed.
      56bcfbb515df
    • Georges Racinet's avatar
      load_repo: main cure for memory leak · 73abd75e439b
      Georges Racinet authored
      This brings down the leaking over 1000 requests from
      55MB to about 5MB. We are not yet forcing garbage collection
      (as `hgwebdir` does).
      
      The `_filteredrepotypes` keeps a correspondence between
      unfiltered repository classes and the filtered version.
      
      The problem is that each new repository is an instance of
      the single-usage class generated in `hgext3rd.topic.reposetup`,
      so these accumulate in `_filteredrepotypes`.
      
      Ironically the mapping seems to be there to avoid some other
      case of leaking:
      
      ```
      # Python <3.4 easily leaks types via __mro__. See
      # https://bugs.python.org/issue17950. We cache dynamically created types
      # so they won't be leaked on every invocation of repo.filtered().
      _filteredrepotypes = weakref.WeakKeyDictionary()
      ```
      
      One could imagine that garbage collection of the repo would also just
      clear its reference from the `WeakKeyDictionary`, but it doesn't
      happen.
      
      A final suprise is that this unlocks the collection of `ui` instances.
      According to investigation made with `guppy3` the class objects were
      actually the ones eating the most memory, but getting rid of `ui`
      instances is also good news.
      73abd75e439b
    • Georges Racinet's avatar
      load_repo: avoid useless ui object copy · e15ae3992048
      Georges Racinet authored
      Found out while investigating heptapod#466 that actually
      the machinery behind `hg.repository` actually performs a
      copy on its own. Our copy was adding pressure on the
      Python memory system. This does not cure the memory leak,
      but it saves about 2MB of leak over 1000 requests, even though
      it doesn't change the fact that none of these ui instances
      are actually collected (seen through instrumentation not
      part of this changeset).
      
      From `localrepo.py` in Mercurial 5.6.1:
      
      ```
      def makelocalrepository(baseui, path, intents=None):
          """Long docstring not cited here."""
          ui = baseui.copy()
          # Prevent copying repo configuration.
          ui.copy = baseui.copy
          (...)
      ```
      
      Note that this last line actually prevents `baseui` (
      would be the copy we were creating) to be freed immediately.
      
      makelocalrepository in turn is called via this backtrace:
      
      ```
        venv/lib64/python3.9/site-packages/mercurial/hg.py(221)repository()
      -> peer = _peerorrepo(
        venv/lib64/python3.9/site-packages/mercurial/hg.py(188)_peerorrepo()
      -> obj = _peerlookup(path).instance(
        venv/lib64/python3.9/site-packages/mercurial/localrepo.py(3214)instance()
      -> return makelocalrepository(ui, localpath, intents=intents)
      > venv/lib64/python3.9/site-packages/mercurial/localrepo.py(517)makelocalrepository()
      -> ui = baseui.copy()
      
      ```
      e15ae3992048
    • Georges Racinet's avatar
      load_repo: using a local variable before returning · 09d6901ca5d7
      Georges Racinet authored
      This will make instrumentation for memory investigation
      easier.
      09d6901ca5d7
    • Georges Racinet's avatar
      Merge branch 'topic/default/blob-tree' into 'branch/default' · e509cf7b74c4
      Georges Racinet authored
      Blob and Tree related service methods
      
      Closes #16, #43, and #44
      
      See merge request !57
      e509cf7b74c4
  2. Apr 06, 2021
  3. Apr 07, 2021
    • Georges Racinet's avatar
      CommitService: implementation of GetTreeEntries · 230354fec952
      Georges Racinet authored
      This relies on the previously listing methods introduced
      in `ManifestMiner`
      
      Closes: #16
      230354fec952
    • Georges Racinet's avatar
      ManifestMiner.iter_dir_with_flat_paths() · c11dcc9cdf5d
      Georges Racinet authored
      This method will be needed for the non recursive case
      of `CommitService.GetTreeEntries`.
      
      The complication is the "flat path" computation, starting
      with its actual definition.
      
      We keep on using a fake changeset class in the tests (with
      a single integration case to tie it up), and we include for
      reference a direct Python translation of the Gitaly algorithm for
      reference.
      
      This algorithm is of course meant for Git, where
      the directory structure is explicit and naturally arborescent,
      but in Mercurial (with the current manifests), it would be O(n^2),
      where n is the total length of the manifest, and that is not
      acceptable.
      c11dcc9cdf5d
    • Georges Racinet's avatar
      ManifestMiner.iter_dir_recursive() · 1409a3e0bcf8
      Georges Racinet authored
      This new method will be needed for the `recursive` request option
      of `CommitService.GetTreeEntries`.
      
      This direct implementation can well be later on superseded by
      better usage of the manifest API.
      
      In the tests, to easily multiply the cases encountered, we use
      a pseudo manifest whose sole purpose is to be an iterator of
      paths. After all, that's about all the method needs.
      This is much lighter that creating actual Mercurial content
      for all the cases. A single integration test case is then enough
      to validate that it really works.
      1409a3e0bcf8
  4. Mar 05, 2021
  5. Feb 11, 2021
    • Georges Racinet's avatar
      BloBService: implementation of GetBlob (singular) · dedad609fdac
      Georges Racinet authored
      The `iter_blob_chunks` now does duplicate the
      `stream.split_batches()` that was introduced actually
      later, but is interesting on its own:
      
      - it could have better performance profile
      - it returns the `is_first` boolean, that allows not to
        repeat oid and size, which callers of `stream.split_batches()`
        IIRC also need in a different case.
      
      Closes #44
      dedad609fdac
  6. Feb 10, 2021
  7. Apr 06, 2021
    • Georges Racinet's avatar
      CommitService.TreeEntry: initial implementation · 3f1bc3eb719d
      Georges Racinet authored
      This method allows to retrieve a specific entry in a Git tree,
      hence itself a tree or a blob, while GetTreeEntries lists the
      entries in a tree.
      
      For instance, on the Rails side, it is currently the method
      called behind `Blob.find`.
      
      The size computation is a bit expensive in case the entry is
      itself a tree for how useful it is supposed to be.
      
      Closes #16
      3f1bc3eb719d
    • Georges Racinet's avatar
      gRPC errors: failed_precondition · 0bce537c7fc5
      Georges Racinet authored
      yet another error helper modelled on the existing ones
      0bce537c7fc5
  8. Apr 01, 2021
    • Georges Racinet's avatar
      file_context: Git file modes · 6ef5de193be5
      Georges Racinet authored
      The `file_context.git_perms` function will be useful in Blob
      related service methods, is easily testable outside of gRPC,
      and was the occasion to start a new Python module dealing
      with `filecontext` instances.
      6ef5de193be5
  9. Mar 20, 2021
  10. Mar 16, 2021
  11. Apr 04, 2021
  12. Mar 04, 2021
  13. Mar 30, 2021
  14. Feb 28, 2021
  15. Apr 01, 2021
Loading