typo, hide counter on empty pages, add short title
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
== Systemy współdzielenia dokumentów w czasie rzeczywistym
|
||||
Budując rozwiązania związane z równoczesnym tworzeniem i modyfikacją tekstu przez więcej niż jednego użytkownika, musimy rozważyć wyzwania napotykane w aktualizacji tworzonego dokumentu, gdzie każdy klient posiada lokalną kopię i nanosi na nie własne zmiany, ale też w międzyczasie musimy nanieść zmiany od pozostałych klientów. W takim systemie mówimy wtedy o zbieżności danych@cite:eventually_consistent - czyli zapewnieniu tego samego stanu między każdym klientem. W przypadku edycji tekstu skupię się na ewentualnej zbieżności, która uwzględnia posiadanie rozbieżnych kopii tego samego źródła danych u każdego z klientów przez pewien czas. Dopiero gdy zostanie zakończona edycja tekstu, zmiany zostają propagowane i nanoszone do pozostałych klientów. Finalnie każdy klient po czasie posiada identyczną kopię dokumentu. Ze strony doświadczeń użytkowania jest to skuteczna strategia ze względu na możliwość zapewnienia płynności interfejsu graficznego oraz z pomocą złożonych mechanizmów umożliwia rozwiązywanie konfliktów między kopiami.
|
||||
|
||||
Wspomniany model nie jest bez wad. Największym problemem jest istnienie konfliktów, których rozwiązanie klienci muszą ustalić za pomocą dodatkowych strategii. Najeczęściej wykorzystywaną jest Last-Write-Wins (LWW). Rozstrzyga ona konflikty poprzez nanoszenie tylko tej zmiany, która jest uznawana jako ostatnia w kolejności zbioru konfliktujących operacji. Ustalanie kolejności nie jest jasno tutaj zdefiniowane. W systemach baz danych takich jak Cassandra@cite:apache_cassandra_documentation oraz SQL Server P2P@cite:microsoft_sql_server_p2p_replication_documentation każdy zapis otrzymuje własny znacznik czasowy, na podstawie którego wybierany jest najmłodszy wpis i nim nadpisywane są zmiany w źródle danych. Zmiany ze starszymi znacznikami są porzucane. Zauważalną wadą LWW jest wysokie ryzyko utraty danych w czasie nanoszenia zmian, ponieważ wszystkie konfliktujące starsze zmiany nie są brane pod uwagę.
|
||||
Wspomniany model nie jest bez wad. Największym problemem jest istnienie konfliktów, których rozwiązanie klienci muszą ustalić za pomocą dodatkowych strategii. Najczęściej wykorzystywaną jest Last-Write-Wins (LWW). Rozstrzyga ona konflikty poprzez nanoszenie tylko tej zmiany, która jest uznawana jako ostatnia w kolejności zbioru konfliktujących operacji. Ustalanie kolejności nie jest jasno tutaj zdefiniowane. W systemach baz danych takich jak Cassandra@cite:apache_cassandra_documentation oraz SQL Server P2P@cite:microsoft_sql_server_p2p_replication_documentation każdy zapis otrzymuje własny znacznik czasowy, na podstawie którego wybierany jest najmłodszy wpis i nim nadpisywane są zmiany w źródle danych. Zmiany ze starszymi znacznikami są porzucane. Zauważalną wadą LWW jest wysokie ryzyko utraty danych w czasie nanoszenia zmian, ponieważ wszystkie konfliktujące starsze zmiany nie są brane pod uwagę.
|
||||
|
||||
W przypadku tekstu jako typu danych, istnieje specjalny wariant ewentualnej zbieżności - silna ewentualna zbieżność. Ten model wykorzystuje specjalne struktury danych, które zapewniają bezkonfliktowe nanoszenie zmian, a ich skuteczność opiera się na matematycznych dowodach@cite:verifying_strong_eventual_consistency.
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ struct NoteInvitation: Identifiable {
|
||||
caption: [Definicja obiektu reprezentującego zaproszenie do edycji notatki],
|
||||
)
|
||||
|
||||
Ostatnim obiektem jest struktura `Peer` przedstawiona w programie 3.4, która jest opisem aktualnego stanu połączenia wykrytego innej instancji systemu w pobliżu użytkownika. Składa się z wartości enumerowanej opisującej stan połączeniao raz identyfikatorem użytkownika w sieci peer to peer. Implementuja ona protokół `Idenfitiable`, by móc zostać poprawnie użyta do rysowania listy dostępnych klientów w pobliżu użytkownika.
|
||||
Ostatnim obiektem jest struktura `Peer` przedstawiona w programie 3.4, która jest opisem aktualnego stanu połączenia wykrytego innej instancji systemu w pobliżu użytkownika. Składa się z wartości enumerowanej opisującej stan połączenia wraz z identyfikatorem użytkownika w sieci peer to peer. Implementuje ona protokół `Identifiable`, by móc zostać poprawnie użyta do rysowania listy dostępnych klientów w pobliżu użytkownika.
|
||||
|
||||
#let peer_struct = [```swift
|
||||
struct Peer: Identifiable {
|
||||
|
||||
@@ -289,6 +289,6 @@ Weryfikacja wymagań niefunkcjonalnych została uzupełniona o pomiary wydajnoś
|
||||
|
||||
Średnie zużycie pamięci RAM przy uruchomionej aplikacji, bez aktywnej sesji edycji, wynosiło 20 MB. Podczas aktywnej sesji peer-to-peer z dwoma połączonymi klientami zużycie wzrastało do 30 MB. Wzrost ten jest spowodowany głównie utrzymywaniem obiektów związanych z sesją `MCSession` oraz obsługą komponentu edycji tekstu `TextEditor`. Nie zaobserwowano wycieków pamięci w trakcie użytkowania.
|
||||
|
||||
Obciążenie procesora w stanie spoczynku wynosiło 0-1%, gdzie przedział maksymalny wynosi 0-600%, ze względu na obecność 6 rdzenii, których zużycie, w zakresie 0-100%, się sumuje. Podczas intensywnej edycji tekstu z jednoczesną synchronizacją obciążenie wzrastało do 30-40% na urządzeniu iPhone 16 Pro. Głównym źródłem obciążenia była obsługa edycji tekstu oraz wysyłanie danych przez framework Multipeer Connectivity.
|
||||
Obciążenie procesora w stanie spoczynku wynosiło 0-1%, gdzie przedział maksymalny wynosi 0-600%, ze względu na obecność 6 rdzeni, których zużycie, w zakresie 0-100%, się sumuje. Podczas intensywnej edycji tekstu z jednoczesną synchronizacją obciążenie wzrastało do 30-40% na urządzeniu iPhone 16 Pro. Głównym źródłem obciążenia była obsługa edycji tekstu oraz wysyłanie danych przez framework Multipeer Connectivity.
|
||||
|
||||
Podsumowując - przeprowadzone testy jednostkowe, scenariuszowe oraz wydajnościowe potwierdzają, że zaimplementowana aplikacja spełnia przyjęte wymagania funkcjonalne i niefunkcjonalne. Architektura oparta na protokole `StorageProvider` umożliwiła efektywne testowanie logiki przechowywania, natomiast manualne scenariusze wykazały stabilność komunikacji P2P w typowych warunkach użytkowania.
|
||||
|
||||
LFS
BIN
Binary file not shown.
+15
-11
@@ -11,14 +11,18 @@
|
||||
#pagebreak()
|
||||
|
||||
#include "Abstract.typ"
|
||||
|
||||
#zut-template([
|
||||
#include "Chapters/0. Introduction.typ"
|
||||
#include "Chapters/1. Theoretical Scope.typ"
|
||||
#include "Chapters/2. Implementation.typ"
|
||||
#include "Chapters/3. Tests.typ"
|
||||
#include "Chapters/4. Summary.typ"
|
||||
#render-bib()
|
||||
#pagebreak(to: "odd")
|
||||
#list-of-figures()
|
||||
])
|
||||
#pagebreak(to: "odd")
|
||||
#zut-template(
|
||||
[
|
||||
#include "Chapters/0. Introduction.typ"
|
||||
#include "Chapters/1. Theoretical Scope.typ"
|
||||
#include "Chapters/2. Implementation.typ"
|
||||
#include "Chapters/3. Tests.typ"
|
||||
#include "Chapters/4. Summary.typ"
|
||||
#pagebreak(to: "odd")
|
||||
#render-bib()
|
||||
#pagebreak()
|
||||
#list-of-figures()
|
||||
],
|
||||
shorttitle: "Aplikacja do współtworzenia notatek z wykorzystaniem technologii peer-to-peer",
|
||||
)
|
||||
|
||||
+1
-1
@@ -92,7 +92,7 @@
|
||||
let chapter-locs = query(heading.where(level: 1))
|
||||
let is-chapter-page = chapter-locs.any(h => counter(page).at(h.location()).first() == pg)
|
||||
|
||||
if not is-chapter-page {
|
||||
if chapter-locs.len() == 0 {} else if not is-chapter-page {
|
||||
// Tytuł bieżącego rozdziału do nagłówka
|
||||
let prev = query(heading.where(level: 1).before(here()))
|
||||
let ch-label = if prev.len() > 0 {
|
||||
|
||||
Reference in New Issue
Block a user